Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/392.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java通用字段_Java_Generics - Fatal编程技术网

Java通用字段

Java通用字段,java,generics,Java,Generics,我有一个角色扮演课。 玩家角色可以扩展(例如,吸血鬼玩家角色vs狼人玩家角色) 我有一个特质类。特征可以扩展(例如,生成或灵知) PlayerCharacter有一个方法,#withTrait(Trait),它将Trait添加到集合中。 PlayerCharacter有一个方法,#applyAllTraits(),它在集合中循环,并将每个集合应用于角色 一个吸血鬼玩家角色应该能够被赋予任何可以应用于玩家角色的特质,以及任何只能应用于吸血鬼玩家角色的特质 所以我添加了一个泛型类型,使Trait 因

我有一个角色扮演课。 玩家角色可以扩展(例如,吸血鬼玩家角色vs狼人玩家角色)

我有一个特质类。特征可以扩展(例如,生成或灵知)

PlayerCharacter
有一个方法,
#withTrait(Trait)
,它将Trait添加到集合中。
PlayerCharacter
有一个方法,
#applyAllTraits()
,它在集合中循环,并将每个集合应用于角色

一个
吸血鬼玩家角色
应该能够被赋予任何可以应用于
玩家角色
特质
,以及任何只能应用于
吸血鬼玩家角色
特质

所以我添加了一个泛型类型,使
Trait

因此,可以有
BasicTrait
Generation

我的难题:

  • 如果PlayerCharacter的特征集合是
    集合
    ,则
    PlayerCharacter
    无法将
    特征
    添加到集合中

  • 如果
    PlayerCharacter
    的特征集合是
    collection>traits=newarraylist();
    具有强度的玩家角色(int str){
    this.str=str;
    归还这个;
    }
    PlayerCharacter with Trait(Trait-Trait){
    this.traits.add(trait);
    归还这个;
    }
    无效applyTraits(){
    forEach((特征t)->t.apply(这个));
    }
    }
    类PlayerCharacter扩展了PlayerCharacter{
    私人长度;
    吸血鬼PlayerCharacter withFangLength(int fangLength){
    this.fangLength=fangLength;
    归还这个;
    }
    }
    抽象类特征{
    无效申请(PC);
    }
    阶级力量{
    私有int str;
    强度(内部结构){
    this.str=str;
    }
    无效应用(PlayerCharacter pc){
    具有强度的pc(str);
    }
    }
    类FangLengthTrait扩展了Trait{
    私人长度;
    牙长特征(内牙长){
    this.fangLength=fangLength;
    }
    无效应用(PlayerCharacter pc){
    带齿长的pc(齿长);
    }
    }
    
    问题是您需要将继承保留为泛型类型信息

    基本上,您必须执行以下操作:

    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 PlayerCharacter{
    
    List我不认为继承是管理这些对象的好方法。查找Strategy模式和Decorator模式,也许其中的一种可能对您有用。您可以尝试interfacesorry,但您的设计有缺陷-
    Trait
    类型的
    PlayerCharacter
    没有多大意义,它应该更像是一个
    Field
    PlayerCharacter
    中,另外:您的术语很混乱,我建议将
    PlayerCharacter
    更改为
    Character
    ,可能还有
    Character
    或类似的内容,这会让事情变得更清楚。另外:
    Trait
    不需要“应用”对于
    字符
    ,只能添加、更改或删除它们。如果你以后能够理清设计,使所有内容都合乎逻辑、一致且易于阅读,这将非常有帮助,即使你是唯一的开发人员。命名法是软件开发中最重要的一点-糟糕的软件名称混乱,会使你的tr脱轨第一个阶段是规划,概念化一个完全清晰的设计——如果这样做了,你在很多事情上的问题就会少很多,问题的解决方案就会一目了然——如果你自己每次都需要重复所有事情并提醒自己最初的目标,那么情况就不是这样了你遇到了一个新/旧问题这让我确信泛型并不是解决这个问题的正确方法。:(我也意识到我可以依靠方法重载,有特点的孩子有更精确的应用方法。这有点棘手,但似乎有效)
    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());
        }
    }