简体   繁体   English

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

[英]Modelling selective inheritance trait in Java?

I'm not sure if I'm asking the right question. 我不确定是否要问正确的问题。 Please correct it if I'm wrong. 如果我错了,请更正它。

I have 3 classes that models inheritance where some subclasses should not inherit a parent attribute. 我有3个建模继承的类,其中某些子类不应继承父属性。

Let's take for example the below classes: 让我们以下面的类为例:

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?
}

I was thinking about using an interface but then it doesn't allow me to hold mutable data for the classes like an abstract class can. 我当时在考虑使用接口,但是那样就不允许我像抽象类那样保存类的可变数据。 For example, I want to hold specific variables pertaining to the Child and Leaf class, such as the position of the child in the list of its parent. 例如,我要保留与Child和Leaf类有关的特定变量,例如孩子在其父列表中的位置。

I can't do this either: 我也不能这样做:

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;
}

Again, how would I model this? 同样,我将如何建模呢?

Your question is confusing as it uses parent/children relationships in terms of reality and programming without specifying which you mean. 您的问题令人困惑,因为它在现实和编程方面使用了父子关系,而没有指定您的意思。 However, I think I have a general understanding as to what you are asking. 但是,我想我对您的要求有一个大致的了解。

I believe what you are looking for is the Composite Pattern 我相信您正在寻找的是复合模式
(See: https://en.wikipedia.org/wiki/Composite_pattern ) (请参阅: https : //en.wikipedia.org/wiki/Composite_pattern

In the following implementation, Child and Childless have become part of the Composite pattern and has been abstracted an extra layer from Root by adding a Person class. 在以下实现中, ChildChildless已成为Composite模式的一部分,并通过添加Person类从Root提取了额外的一层。

So you would have 所以你会

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 is the "component" and now has the position field because every child has a position in the list of the parent. Person是“组件”,现在具有position字段,因为每个孩子在父母列表中都有一个位置。

Child is the "composite" and now has the children field because every child that is not barren can have more children. Child是“复合人”,并且现在拥有children领域,因为每个不贫瘠的孩子都可以有更多的孩子。

Childless is the "leaf" because it can no longer have more children. Childless是“叶子”,因为它不能再有更多的孩子。

Also, keep in mind that fields that are private cannot be accessed by subclasses, so use protected instead. 另外,请记住,子类无法访问private字段,因此请使用protected

A simple flip of not having Leaf be a subclass of Child , and moving the field, works 不让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.
}

This model makes more sense IMO. 这种模式使IMO更有意义。 Every LeafNode and InnerNode are considered Nodes, but only InnerNodes have children. 每个LeafNode和InnerNode都被视为节点,但是只有InnerNodes拥有子级。

If you want, you could even add an abstract getter to Node to return children, and have LeafNode return null or an empty list: 如果需要,您甚至可以向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
    }
}

This accomplishes roughly what you set out to do - only some Nodes (InnerNodes) will actually have children, but you can attempt to access the children of an arbitrary Node instance without casting. 这大致完成了您打算执行的操作-只有某些节点(InnerNodes)实际上将具有子级,但是您可以尝试访问任意Node实例的子级而无需强制转换。 The following is now possible: 现在可以进行以下操作:

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

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

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