У меня есть интерфейс, чтобы описать, когда класс может создать «следующую» версию самого себя:
public interface Prototypeable<Type extends Prototypeable<Type>> {
public Type basePrototype(); // the zeroth raw instance of Type
public Type nextPrototype(); // the next instance of Type
}
для использования с
public class Prototyper {
public static <Type extends Prototypeable<Type>> List<Type> prototypeFactor(int numberOfInstances, Type proto) {
List<Type> result = new ArrayList<Type>(numberOfInstances);
Type holder = proto.basePrototype();
result.add(holder);
for (int i=1; i<numberOfInstances;i++) result.add(holder = holder.nextPrototype());
return result;
}
Теперь у меня есть базовый класс A implements Prototypeable<A>
и подкласс AButMore extends A
. Я хотел бы иметь AButMore extends A implements Prototypeable<AButMore>
, но это не разрешено (не может реализовать универсальные интерфейсы несколько раз с разными классами). Также обратите внимание, что A
и AButMore
оба реализуют некоторые другие интерфейсы, и что реализация идентична от A
до AButMore
.
Предложения обойти это? Кажется, я не могу разобраться с общей проблемой, поэтому я рассмотрел несколько альтернативных вариантов:
псевдо-декорирование обоих классов, т. Е. Наличие базового класса, который не реализует интерфейс Prototypeable
, наследование от него в надлежащий подкласс и последующее расширение обоих классов до прототипируемых версий самих себя. Недостатком, кажется, является изобилие классов.
не расширяет A
до AButMore
и вместо этого создает AButMore
из A
s и делегирует все реплицированные методы. Тем не менее, код делегата всегда кажется мне глупым, особенно когда каждый метод, который может быть унаследован, будет делегирован без изменений.
с Prototypeable
укажите Object
в качестве типа возвращаемого значения и с фабрикой для параметра приведения Class
. Недостатком здесь является то, что при неправильном использовании это может привести к небезопасным броскам.
РЕДАКТИРОВАТЬ : Чтобы уточнить: цель состоит в том, чтобы создавать экземпляры, имеющие некоторую последовательную зависимость, без наличия переменной класса. Простейшим примером было бы, если бы у каждого из них была переменная индекса - basePrototype предоставил бы экземпляр с 0 индексами, а nextPrototype () предоставил бы экземпляр с индексом + 1 (на основе индекса экземпляра, из которого был вызван метод). Этот конкретный случай немного упрощен (и, вероятно, может быть реализован более простым способом), но охватывает идею.
РЕДАКТИРОВАТЬ : Для дальнейшего пояснения, вот точная текущая реализация (я использую третий альтернативный вариант выше):
public class BuildFromPrototype {
public static <T extends Prototypeable> List<T> build(int buildCount, Class<T> protoClass, T prototype) {
if (protoClass==null || prototype==null || buildCount<=0) return null;
if( protoClass.isInstance(prototype.basePrototype()) && protoClass.isInstance(prototype.nextPrototype()) ) {
List<T> result = new ArrayList<T>(buildCount);
T pHolder = protoClass.cast(prototype.basePrototype());
result.add(pHolder);
for (int i=1;i<buildCount;i++)
result.add(pHolder = protoClass.cast(pHolder.nextPrototype()));
return result;
} else return null;
}
public interface Prototypeable {
public Object nextPrototype();
public Object basePrototype();
}
}
Я думаю, что это обрабатывает неправильное использование (возврат null
является одним из вариантов, Exception
также было бы разумно), но тестирование на допустимые приведения может быть дорогостоящим. Эта форма литья также может быть дорогой - я не знаю много о классе Class
.