为什么我们不能使用超类的引用变量来访问其子类的方法(超类中不可用的方法)?

时间:2017-07-15 08:07:18

标签: java polymorphism run-time-polymorphism

我知道,无论实际对象是什么,引用变量引用的是什么,我可以在引用上调用的方法依赖于变量的声明类型(代码的第15行)。我想要知道为什么这样。为什么类用户不能使用Shape类型的引用变量来调用它的子类方法drawCircle()?

$store = New-Object System.Security.Cryptography.X509Certificates.X509Store("\$server_name\My","LocalMachine")

$store.Open("ReadOnly")
$store.Certificates

你可以向我解释一下对象级别会发生什么吗?我是java新手。

4 个答案:

答案 0 :(得分:0)

首先,您忘记了Circle的{​​{1}}子类。

然后你说:

  

我可以调用引用的方法取决于声明的方法   变量的类型

Shape参数也是一个变量:

Shape myShape

因此,对于局部变量或字段变量,编译器仅依赖声明的类型来绑定调用的方法。
由于 public void display(Shape myShape){ ... myShape.drawCircle(); } 类用作声明变量的类型,因此只能调用此类的方法。

答案 1 :(得分:0)

如果你确定myShape是一个圆圈,你可以明确地将其转换为一个 ((Circle)myShape).drawCircle();Circle myCircle = (Circle)myShape; myCircle.drawCircle();但如果您这样做且实际上并非Circle,那么您将获得ClassCastException

一般来说,你想尝试避免这种类型的渲染,因为它的代码味道会暗示你的设计有点偏差。 (有时你确实需要这样做,但它没有利用多态性。)

要利用多态性,您可以将Shape定义为displayShape()作为抽象方法,然后代替drawCircle()drawSquare()等... {的每个子类{1}}将拥有自己的Shape方法版本,而在displayShape()本身则可以: Shape这是告诉编译器的一种方式"所有我的子类都有这个displayShape()方法,所以当有人在我的一个上调用displayShape()时,使用在该子类中定义的那个"。

例如:

public abstract displayShape();

答案 2 :(得分:0)

reading about polymorphism怎么样。

public abstract class Shape {
   public abstract void draw();
}

public class Circle extends Shape {
    @Override
    public void draw() {
       System.out.println("Circle drawed");
    }
}

public class Triangle extends Shape {
    @Override
    public void draw() {
       System.out.println("Triangle drawed");
    }
}

public class Test() {
   public static void display(Shape shape) {
      shape.draw();
   }

   public static void main(String[] args) {
      //how can you define "shape" in real world? its triangle or... -> abstraction
      Circle c = new Circle();
      Triangle t = new Triangle();

      display(c);
      display(t);
   } 
}

答案 3 :(得分:0)

编译器只知道myShapeShape类型的引用变量,它只包含一个方法displayShape(),因此根据编译器,不可能调用方法drawCircle()类不包含的Shape

编译器不关心此变量在运行时将保留的对象。您可以在稍后的某个时间点从Shape类扩展另一个类,并使用myShape引用来保存该子类对象。编译器只关心编译时myShape的类型。

如果您的Circle课程碰巧覆盖了displayShape()方法,如下所示:

public class Circle extends Shape {
    public void displayShape() {
        System.out.println("I am a Circle!");
    }

    public void drawCircle() {
    // Implementation here
    }
}

在运行时发生的唯一决定是调用哪个displayShape()方法。