我有一个PlayerCharacter类。 PlayerCharacter可以扩展(例如,VampirePlayerCharacter vs WerewolfPlayerCharacter)
我有一个特质课程。特质可以扩展(例如,代或Gnosis)。
PlayerCharacter
有一个方法#withTrait(Trait)
,可以将Trait添加到集合中。
PlayerCharacter
有一个方法#applyAllTraits()
,它循环遍历集合并将每个方法应用于角色。
VampirePlayerCharacter
应该能够提供适用于Trait
的任何PlayerCharacter
,以及只适用于{{1}的任何Trait
}}
所以我添加了一个通用类型,使VampirePlayerCharacter
因此,可以有Trait<PC extends PlayerCharacter>
和BasicTrait<PlayerCharacter>
我的难题:
如果PlayerCharacter的特征集合为Generation<VampirePlayerCharacter>
,则Collection<Trait<PlayerCharacter>>
无法将VampirePlayerCharacter
添加到集合中。
如果Trait<VampirePlayerCharacter>
的特征集合为PlayerCharacter
,则Collection<Trait<? extends PlayerCharacter>>
可以向集合中添加VampirePlayerCharacter
。但是,Trait<VampirePlayerCharacter>
无法再遍历这些特征,因为它们的类型不确定(可能是PlayerCharacter
或Trait<PlayerCharacter>
或Trait<VampirePlayerCharacter>
或......)
如果Trait<WerewolfPlayerCharacter>
的特征集合为PlayerCharacter
,那么Collection<Trait<? super PlayerCharacter>>
无法添加VampirePlayerCharacter
,因为Trait<VampirePlayerCharacter>
不是超级类型VampirePlayerCharacter
我觉得更专业的特质只需要在他们的应用方法中使用强制转换,如果你不恰当地设置它们,它们会爆炸 - 但我是某些这不是一个新问题,我只是无法解决问题。
PlayerCharacter
答案 0 :(得分:2)
问题是您需要将继承保留为泛型类型信息。
基本上你必须做类似的事情:
class PlayerCharacter<P extends PlayerCharacter<P>> {
List<Trait<? super P>> myTraits;
}
class VampirePlayer extends PlayerCharacter<VampirePlayer> {...}
abstract class Trait<P extends PlayerCharacter<P>> {
abstract void apply(P player);
}
class FangLengthTrait extends Trait<VampirePlayer> {...}
但是,它开始变得非常笨重。你可以通过从作文中接近来改善这种情况:
class Attributes {}
class Base extends Attributes {
int strength;
}
class Vampire extends Base {
int fangLength;
}
class Player<A extends Attributes> {
final A attributes;
final List<Trait<? super A>> traits = new ArrayList<>();
Player(A attributes) {
this.attributes = attributes;
}
void applyTraits() {
for(Trait<? super A> t : traits)
t.apply(this);
}
}
interface Trait<A extends Attributes> {
void apply(Player<? extends A> player);
}
class StrengthTrait implements Trait<Base> {
@Override
public void apply(Player<? extends Base> player) {
player.attributes.strength = 1000;
}
}
class FangLengthTrait implements Trait<Vampire> {
@Override
public void apply(Player<? extends Vampire> player) {
player.attributes.fangLength = 100;
}
}
final class Factory {
private Factory() {}
public static Player<Base> newPlayer() {
return new Player<Base>(new Base());
}
public static Player<Vampire> newVampire() {
return new Player<Vampire>(new Vampire());
}
}
我个人觉得它仍然很笨重。如果您主要使用这些Trait
构建对象,则可能会考虑使用构建器或工厂,因此您不需要使用泛型。