Java中方法访问修饰符的继承

Java中方法访问修饰符的继承,java,inheritance,Java,Inheritance,我正在玩继承的游戏,试图完全理解它: 我已经创建了一个带有私有方法的父类,并在子类中重写它并将其公开。我还为每个类重写了不同的toString方法。看起来像这样: public class testparent { public String toString(){ return ("One and two boobaloo"); } private void hitMe(){ System.out.println("BAM");

我正在玩继承的游戏,试图完全理解它:

我已经创建了一个带有私有方法的父类,并在子类中重写它并将其公开。我还为每个类重写了不同的toString方法。看起来像这样:

public class testparent {
    public String toString(){
        return ("One and two boobaloo");
    }
    private void hitMe(){
        System.out.println("BAM");
    }
}

public class testbaby extends testparent{
    public String toString() {
        return "Bananas";
    }
    public void hitMe(){
        System.out.println("BAMBAM");
    }
    public static void main(String[] args){
        testbaby testy = new testbaby();
        testparent test2 = testy;
        System.out.println(test2);
        //test2.hitMe(); //????? not allowed
        System.out.println(testy);
        testy.hitMe();
    }
}

现在,为什么打印这两个对象都会产生“香蕉”,但我不能使用这两个类的hitMe()方法呢?

基本上,因为当您将
test2
声明为
testparent
类型的变量时,您故意放弃了
test2
实际上是一个
testbaby
的知识

这是继承点的一部分——任何使用
test2
的代码都只允许假定它是
testparent
testparent
的子类,并且该代码必须适用于所有
testparent
对象,即使不是
testbaby
对象

仅供参考,就
testParent
之外的任何内容而言,
testParent.hitMe()
方法甚至不存在(除了一些基于反射的邪恶事物,在这个阶段您不应该担心)。即使是
testbaby
也不知道
testParent.hitMe()
方法。

这是因为方法和语言本身

Java是静态类型的,具有动态绑定,因此:

  • 方法
    hitMe
    只能在
    testbaby
    声明的变量上调用,因为它在
    testparent
    中是私有的,并且由于静态类型,Java必须确保在运行时确实可以调用该方法
  • 方法
    toString
    可以在两个对象上调用(因为它甚至继承自
    Object
    ),在运行时有效调用哪一个方法是根据运行时实例而不是根据变量声明选择的(因为动态绑定)
根据动态绑定方法,方法的正确和运行时实现是在运行时根据对象的实际实例而不是声明的实例来选择的

这意味着,即使您将
test2
声明为
testparent
,它仍然是
testbaby
对象(因为您正在为它分配一个
testbaby
实例)。在运行时,正确的实现将是子级的实现


但是这是完全合法的,因为
testbaby
testparent

我认为
testparent
中的
hitMe
应该是私有的。哎呀,你是对的——你应该遵循java编码约定,其中包括:类名应该以大写字母开头,因此,您应该将
testbaby
重命名为类似于
testbaby
的名称,而
testparent
也是如此。重要的关键词:静态键入不在本例中。无法编译来自testparent类型的调用(如果它编译了,则不会通过验证),因为testparent方法是私有的。我不是在谈论
hitMe
方法,我是在谈论打印“香蕉”+1作为术语:使用动态绑定和静态类型来解释手头的两个问题。您还应该链接到维基百科页面,解释这些概念,以便更好地回答问题。