繁体   English   中英

在Java中建模选择性继承特征?

[英]Modelling selective inheritance trait in Java?

我不确定是否要问正确的问题。 如果我错了,请更正它。

我有3个建模继承的类,其中某些子类不应继承父属性。

让我们以下面的类为例:

abstract public class Root{
    // Has some attributes that must be inherited by it's sub classes
    List<Child> children;
}

abstract public class Child extends Root {
    // Has the root's attributes, plus additional attributes pertaining to the child class, including the position.
    private int position;
}

abstract public class Leaf extends Child {
    // this class inherits all attributes of child class but it does not have any children
    // How would I exclude the children attribute here?
}

我当时在考虑使用接口,但是那样就不允许我像抽象类那样保存类的可变数据。 例如,我要保留与Child和Leaf类有关的特定变量,例如孩子在其父列表中的位置。

我也不能这样做:

abstract public class Leaf {
    // This child does not have a parent, but then again, it's not considered a child either because it comes before the Root who has children.
}

abstract public class Root extends Leaf {
    List<Child> children;
}

abstract public class Child extends Root {
    private int position;
}

同样,我将如何建模呢?

您的问题令人困惑,因为它在现实和编程方面使用了父子关系,而没有指定您的意思。 但是,我想我对您的要求有一个大致的了解。

我相信您正在寻找的是复合模式
(请参阅: https : //en.wikipedia.org/wiki/Composite_pattern

在以下实现中, ChildChildless已成为Composite模式的一部分,并通过添加Person类从Root提取了额外的一层。

所以你会

abstract public class Root {
    //attributes that everything has
}

abstract public class Person extends Root {
    protected int position; //All children have parents
    //other attributes
}

abstract public class Child extends Person {
    protected List<Person> children; //But only Child has more children
    //other attributes
}

abstract public class Childless extends Person{
    //attributes
}

Person是“组件”,现在具有position字段,因为每个孩子在父母列表中都有一个位置。

Child是“复合人”,并且现在拥有children领域,因为每个不贫瘠的孩子都可以有更多的孩子。

Childless是“叶子”,因为它不能再有更多的孩子。

另外,请记住,子类无法访问private字段,因此请使用protected

不让Leaf成为Child的子类的简单翻转,然后移动字段即可

abstract public class Node {
    private int position; //Every Node can have a position
}

public class InnerNode extends Node { //Renamed for clarity
    List<Node> children; //Children can be InnerNodes or Leafs 
}

abstract public class LeafNode extends Node {
    //As this is no longer an extension of InnerNode, it won't have the children field.
}

这种模式使IMO更有意义。 每个LeafNode和InnerNode都被视为节点,但是只有InnerNodes拥有子级。

如果需要,您甚至可以向Node添加一个抽象getter以返回子代,并使LeafNode返回null或空列表:

abstract public class Node {
    private int position; //Every Node can have a position

    public abstract List<Node> getChildren();
}

public class InnerNode extends Node { //Renamed for clarity
    List<Node> children; //Children can be InnerNodes or Leafs 

    public List<Node> getChildren(){
        return new ArrayList<>(children);
    }
}

abstract public class LeafNode extends Node {
    //As this is no longer an extension of InnerNode, it won't have the children field.

    public List<Node> getChildren() {
        return new ArrayList<>(); //Empty
    }
}

这大致完成了您打算执行的操作-只有某些节点(InnerNodes)实际上将具有子级,但是您可以尝试访问任意Node实例的子级而无需强制转换。 现在可以进行以下操作:

Node n = ...
List<Node> children = n.getChildren();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM