Java 更改继承类中方法的可见性

Java 更改继承类中方法的可见性,java,inheritance,Java,Inheritance,我有两个类:GraphNode和BTNode扩展GraphNode。我有一个方法: public GraphNode.addChild(GraphNode node) 因为GraphNode可能有很多孩子 和两种方法: public BTNode.addLeftChild(BTNode left) public BTNode.addRightChild(BTNode right) 因为BTNode可能只有两个子节点 如何限制对BTNode类中继承的addChild(GraphNode节点)方

我有两个类:
GraphNode
BTNode扩展GraphNode
。我有一个方法:

public GraphNode.addChild(GraphNode node)
因为GraphNode可能有很多孩子 和两种方法:

public BTNode.addLeftChild(BTNode left)
public BTNode.addRightChild(BTNode right)
因为BTNode可能只有两个子节点

如何限制对BTNode类中继承的
addChild(GraphNode节点)
方法的公共访问?我不希望从该级别公开访问它(同时保持从GraphNode类的公开访问)

如果从类(或接口)扩展(或实现),则父级将指定方法的整个签名。没有任何内容您可以对其进行更改,如果您的家长将该方法指定为公共,则始终需要将其设置为公共

否则,在像
((父)子)这样进行强制转换时,您将遇到问题。对象本身是
子类
,但视图被缩减为
父类
类。该方法从
子类
调用,因此它将是私有的,尽管您将其强制转换为
父类
,父类将其指定为公共的

但是,您可以执行以下操作:

public class Child extends Parent {
    @Override
    public void theMethod() throws UnsupportedOperationException {
        throw new UnsupportedOperationException();
    }

    private void otherMethod {
        // Do something
    }
}

但请注意,说“我正在扩展XY类,但不支持它的所有方法”并不是最好的设计。这是一个迹象,表明父类(或体系结构的其他部分)本来可以构建得更加模块化。

不可能降低子类中方法的可见性。子类必须是基类的有效实例。

正如您在前面的答案中所看到的,不可能更改子类中的
public
方法的可见性。但如果您是
GraphNode
类的设计者,则可以使用另一个类层次结构:

public abstract class BaseNode {
    protected final Map<String, GraphNode> children = new HashMap<>();

    protected void addChild(String id, GraphNode node) {
        children.put(id, node);
    }
}

public class GraphNode extends BaseNode {
    public void addChild(GraphNode node) {
        children.put(String.valueOf(System.currentTimeMillis()), node);
    }
}

public class BTNode extends BaseNode {
    private static final String LEFT = "left";
    private static final String RIGHT = "right";

    public void addLeftChild(BTNode node) {
        addChild(LEFT, node);
    }

    public void addRightChild(BTNode node) {
        addChild(RIGHT, node);
    }
}
公共抽象类BaseNode{
受保护的最终映射子项=新HashMap();
受保护的void addChild(字符串id,GraphNode节点){
put(id,node);
}
}
公共类GraphNode扩展了BaseNode{
公共void addChild(GraphNode节点){
put(String.valueOf(System.currentTimeMillis()),节点);
}
}
公共类BTNode扩展了BaseNode{
私有静态最终字符串LEFT=“LEFT”;
私有静态最终字符串RIGHT=“RIGHT”;
公共void addLeftChild(BTNode节点){
addChild(左,节点);
}
public void addRightChild(BTNode节点){
addChild(右,节点);
}
}

您不能这样做,但您可以实现
addChild
,并让它抛出一个异常,并显示一条良好的错误消息,解释为什么不应该在这里使用此方法以及应该使用什么。现在,尽管如此,也许您应该重新考虑继承,因为它觉得
BTNode
毕竟与
GraphNode
没有太多的共同点……您可能不得不问自己,从父类继承是正确的方法吗?你在试图违反那边的利斯科夫替换原则。我想你们应该重新考虑你们的设计。我在考虑设计,它看起来确实是个问题。然而,我不明白为什么会这样,因为BTNode和GraphNode之间的唯一区别是第一个节点可能只有两个子节点。二叉树确实是图形的一个特殊版本,不是吗?我不喜欢让用户使用这个方法只抛出一个异常的想法。但也许解决方案是让他只添加两个子项(假设左和右对用户不重要,所以只按顺序分配它们),然后在用户尝试添加更多子项时引发异常?同样,正方形是矩形的特殊版本,但您不会从矩形继承正方形,否则你就违反了利斯科夫的原则:谢谢你的回答。现在很清楚为什么这样的行动是不可能的。而且,tbh,我以前从未见过这种异常;)但是我不喜欢让用户调用一个方法只抛出一个异常的想法,我现在知道了如何正确使用它。不客气。大多数此类问题都来自于不适当的架构/结构,只需使用更合适的架构/结构即可避免。您是对的,说“我正在扩展XY类,但不支持它的所有方法”不是最好的设计。这是一个迹象,表明父类本来可以构建得更加模块化。很高兴你找到了一个更好的:)