Подтвердить что ты не робот

Объявление статических общих переменных в общем классе

Я читал, что вы не можете объявлять статические переменные/методы внутри родового класса, и я действительно не знаю, как решить мою проблему или обойти ее, поэтому я прошу вашего руководства.

То, что я хочу, - это общий "индекс", который расширит все мои основные классы. Я создаю игровой движок, и пример состоит в том, что у меня будут разные игры, которые все продлят State, который, в свою очередь, расширяет Nexus<State>. Причина, по которой я хочу статическую голову и хвост, - это сохранить связанный список всех игр, так как они добавлены в этот список при создании.

Другим примером является то, что у меня будут разные игровые объекты, которые все расширяют GameObject, который, в свою очередь, расширяет Nexus<GameObject>.

Это индекс с именем Nexus:

public abstract class Nexus<T> 
{

    private static T head = null;
    private static T tail = null;

    private T next = null;
    private static int num = 0;

    protected Nexus() { this.Add( (T)this ); }

    public T Add( T obj )
    {

        ((Nexus)obj).next = null;
        if( num++ == 0 ) head = tail = obj;
        else             tail = ( tail.next = obj );

        return obj;

    }

}

Если у кого-то есть другое решение или обходной путь, я все уши!

4b9b3361

Ответ 1

Попробуйте этот подход: определите метод protected abstract, который реализует подклассы для возврата объекта static для своего класса.

Возможны некоторые логические проблемы и т.д., но основы ответа здесь (т.е. компилируются):

EDITED: теперь делегирование в HeadAndTail

/** <T> A subclass of Nexus */
abstract class Nexus<T extends Nexus<T>> { // This syntax lets you confine T to a subclass of Nexus
    private T next;

    protected Nexus() {
        this.add((T) this);
    }

    public T add(T obj) {
        // Delegate to HeadAndTail
        return getHeadAndTail().add(obj);
    }

    /** @return a static for the class */
    protected abstract HeadAndTail<T> getHeadAndTail();
}

/** Bundled into one Object for simplicity of API */
class HeadAndTail<T extends Nexus<T>> {
    T head = null;
    T tail = null;
    int num = 0;

    public T add(T obj) {
        obj.next = null;
        if (num++ == 0)
            head = tail = obj;
        else
            tail = tail.next = obj;

        return obj;
    }
}

class ConcreteNexus extends Nexus<ConcreteNexus> {
    // This is the static object all instances will return from the method
    private static HeadAndTail<ConcreteNexus> headAndTail = new HeadAndTail<ConcreteNexus>();

    protected HeadAndTail<ConcreteNexus> getHeadAndTail() {
        return headAndTail; // return the static
    }
}

Ответ 2

Генераторы Java сильно отличаются от генераторов С#. Существует стирание типа, поэтому вы не можете сказать что-то вроде Nexus<T>.aStaticPublicField (как в С#). Вы можете сказать только Nexus.aStaticPublicField. Невозможно узнать, что такое общий тип (поскольку у вас нет экземпляра), поэтому вы не можете иметь статическое поле типа T.

Ответ 3

согласно http://download.oracle.com/javase/tutorial/java/IandI/abstract.html

Члены класса - Абстрактный класс может иметь статические поля и статические методы. Вы можете использовать эти статические члены с ссылкой на класс, например AbstractClass.staticMethod(), как и с любым другим классом.

Но я еще не проверил это сам

Ответ 4

Набор статических полей - не очень хороший способ добиться этого. Я не совсем понимаю ваши требования, но, похоже, лучший способ - изменить подпись конструктора для этого класса для передачи в глобальном объекте индекса.

То есть вместо этого:

protected Nexus() { this.Add( (T)this ); }

... вы могли бы сделать это вместо этого:

protected Nexus(GameStateIndex<T> index) { index.Add(this); }

Это правильно отделяет обязанности отслеживания состояния игры и отслеживания индекса всех состояний игры. (См. " Принцип единой ответственности".) Он также явно показывает, что создание объекта состояния связано с зависимостью от индексации, которая правильна.