【问题标题】:Child class method cannot be accessed when a child class object has a reference of parent type and parent class dont have the same child class method [duplicate]当子类对象具有父类型的引用并且父类没有相同的子类方法时,无法访问子类方法[重复]
【发布时间】:2018-12-27 04:57:25
【问题描述】:

无法使用以下行从子类访问方法,

Parent p = new Child(); p.print();

假设我在 Child 类中有一个方法 print(),并且在 Parent 类中 NOT 有相同的方法。在这种情况下,我们无法使用上面的代码行访问子类方法print()。但请注意,如果我们在父类中有相同的方法print(),那么我们可以使用上面的代码访问它。

现实生活中可能没有这样的场景,但如果我们没有在父类中定义相同的方法,我试图理解为什么我无法使用 Parent 类型的子对象访问子类print()

示例代码如下:

public class Main {

    public static void main(String[] args)
    {

        Parent p = new Child();
        p.print(); //Compiler throws an error saying "cannot resolve print method".


    }

}

class Parent {
    int x = 10;


}

class Child extends Parent {

    void print(){
        System.out.println("Child");
    }

    int x = 20;
}

更多解释 - 如果我在父类中定义 print() 方法,那么我可以使用 Parent 类型的对象访问子类 print() 方法。所以我假设我们不能说 parent 类型的对象只能访问父类中定义的成员/方法。

另外,我知道我们可以通过将父类型转换为子类型来访问子方法。我想知道为什么我们不能在没有强制转换的情况下访问子类方法,如果我们没有在父类中定义相同的方法。

我已编辑问题以确保这与其他问题无关 - Calling a subclass method from superclass

【问题讨论】:

  • 其实很简单:Parent 没有名为print 的方法。您声明 p 是父母。编译器看到了,去寻找它的print 方法并且......没有-> 错误。如果你在Parent 中声明它,现在它会被发现,并且在运行时中像往常一样调用Child 类中的覆盖方法...
  • 另一种选择是将对象转换为实际的孩子。子子 = (子)p; -> 这应该使该方法也可以访问。
  • @MalteHartwig not a duplicate bcz 您提到的是找到一种在引用具有 Parent 类型时调用子方法的方法,并且我们可以使用类型转换来实现。但在我的问题中是不同的。请仔细阅读问题。
  • 据我所知,您的问题仍然与您链接的问题重复。仅仅否定您的问题并不会使其他答案无用;它仍然应该解释为什么你不能在不强制转换或拉起方法的情况下访问孩子的方法。此外,本的评论是一个很好的总结。您可以在 Parent 类型中强制转换或定义(抽象)方法。否则,不,您无法访问它。
  • “如果我在父类中定义 print() 方法,那么我可以使用 Parent 类型的对象访问子类的 print() 方法。”不,你不能。您对引用与对象感到困惑。 Parent 对象甚至不知道任何 Child 类,但是当您在 Parent reference 上调用方法时,它将调用父版本或子版本,具体取决于实际对象以及 Child 对象是否已覆盖该方法。

标签: java


【解决方案1】:

当父级没有声明方法(作为具体或抽象方法)时,子级在父变量中实例化时将无法使用该方法。您可以使用以下代码示例来使用它

Parent p = new Child(); 
if(p instanceof Child){
    ((Child) p).print();
}

这背后的解释是变量 p 在运行时实际上并不知道其中存储了哪个子实例(可能有多个子实例,但只有一个具有 print() 方法。也许你会在编译时知道存储在Parent p 中的对象的真实类型,但执行是另一个世界。所以如果 p 对象是 Child 的实例,这意味着 p 被键入为 Child 或其子之一,你可以将其转换为((Child) p),并且所有方法都将被识别为好像是一个孩子(因为它是)。

注意,你可以强制转换一个非 Casteable 的类,你会遇到 ClassCastException。在这个具体示例中,没有必要编写 if 语句,因为我们确定 p 类型,但有时在运行时事情会变得混乱,我们不知道存储在哪里,因此确保你的铸件的健全性变得必不可少的。谈到转换变量,如果您只希望 Child 类访问方法 print 而不是它的子类,您可以使用

Parent p = new Child(); 
if(p.getClass() == Child.class){
    ((Child) p).print();
}

如果您不想强制转换孩子并且您的父类适合使用方法打印(并非总是一个选项),正如您所说,您可以将它声明为父类中的具体方法并覆盖该方法孩子)

class Parent {
    int x = 10;
    void print(){
        System.out.println("Parent");
    }
}

或者您可以在父级中将方法声明为抽象,并且所有子级都必须实现它,但是只要它必须是抽象的,您就无法创建父级的对象。

abstract class Parent {
    int x = 10;
    abstract void print();
}

恢复,如果父母有孩子,孩子将拥有父母的所有方法,但只要是父母,就没有孩子的任何方法。将需要铸造。如果方法 print 写在子进程和父进程中,覆盖最低的方法将是执行的方法(在这种情况下是子方法)。另外,您可以使用在父级中使用 'super' 实现的方法(与构造函数中相同)

class Child extends Parent {

    void print(){
        super.print("Child");
    }

    int x = 20;
}

【讨论】:

  • 其实child可以使用,问题是它没有声明为Child,而是声明为Parent。问题是父母不能使用它
  • 谢谢你,我认为我对英语的严重使用使一些观点难以理解,我已经查看了答案
【解决方案2】:
Parent p = new Child();

您正在使用子类创建父对象。因此,Parent 对象 p 没有 print() 方法很简单。但是 Child 对象具有 print() 方法,因此如果您创建 Child 对象,则可以从 Child 类访问方法 print()。

这里方法的优先级发挥了作用。如果两个类中都有 print() 方法,则子类方法优先于父类方法。

注意:继承是单向的而不是双向的。

【讨论】:

    猜你喜欢
    • 2021-10-02
    • 2017-07-15
    • 2021-03-01
    • 2018-06-03
    • 1970-01-01
    • 2013-03-01
    • 2016-04-05
    • 2014-10-04
    • 1970-01-01
    相关资源
    最近更新 更多