Объявление статических общих переменных в общем классе
Я читал, что вы не можете объявлять статические переменные/методы внутри родового класса, и я действительно не знаю, как решить мою проблему или обойти ее, поэтому я прошу вашего руководства.
То, что я хочу, - это общий "индекс", который расширит все мои основные классы.
Я создаю игровой движок, и пример состоит в том, что у меня будут разные игры, которые все продлят 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;
}
}
Если у кого-то есть другое решение или обходной путь, я все уши!
Ответы
Ответ 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); }
Это правильно отделяет обязанности отслеживания состояния игры и отслеживания индекса всех состояний игры. (См. " Принцип единой ответственности".) Он также явно показывает, что создание объекта состояния связано с зависимостью от индексации, которая правильна.