Объявление статических универсальных переменных в универсальном классе - PullRequest
13 голосов
/ 05 июля 2011

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

То, что я хочу, это общий «индекс», который будут расширены всеми моими основными классами. Я создаю игровой движок, и пример тому, что у меня будут разные игровые состояния, которые расширяют 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;

    }

}

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

Ответы [ 4 ]

10 голосов
/ 05 июля 2011

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

9 голосов
/ 05 июля 2011

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

Могут быть некоторые проблемы с логикой и т. Д., Но основы ответа здесь (т.е. это компилируется):

РЕДАКТИРОВАНИЕ: Теперь делегирование в 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
    }
}
1 голос
/ 05 июля 2011

в соответствии с http://download.oracle.com/javase/tutorial/java/IandI/abstract.html

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

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

0 голосов
/ 05 июля 2011

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

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...