为什么我们不能使用 super class 的引用变量来访问其 subclass 的方法(super class 中不可用的方法)?
why cant we use a reference variable of super class to access methods of its subclass(methods not available in super class)?
我知道,无论引用变量引用的实际对象是什么,我可以调用引用的方法取决于变量的声明类型(在代码的第 15 行)。我想知道为什么so.Why用户不能class使用Shape类型的引用变量s调用它的subclass方法drawCircle()?
public class Shape{
public void displayShape(){
System.out.println("shape displayed");
}
public class Circle extends Shape{
public void drawCircle(){
System.out.println("circle drawn");
}
public class Test{
p.s.v.main(String[] a){
Circle c=new Circle();
Shape s=new Shape();
display(c);
display(s);
public void display(Shape myShape){
myShape.displayShape();//possible for ref variable c and s
myShape.drawCircle();//not possible for reference var s
}
}
}
你能解释一下在对象级别发生了什么吗?我是 java 的新手。
首先,您忘记制作 Shape
的 Circle
subclass。
然后你说:
The methods i can call on a reference is dependent on the declared
type of the variable
但是Shape myShape
参数也是一个变量:
public void display(Shape myShape){
...
myShape.drawCircle();
}
所以这里也是,对于局部变量或者字段变量,编译器只依赖声明的类型来绑定调用的方法。
由于 Shape
class 用作声明变量的类型,因此只能调用此 class 的方法。
如果您确定 myShape 是一个 Circle,您可以明确地将其转换为一个
((Circle)myShape).drawCircle();
或 Circle myCircle = (Circle)myShape; myCircle.drawCircle();
但如果你这样做并且它实际上不是 Circle
那么你将得到 ClassCastException
。
通常,您想尝试避免这种类型的转换,因为它有点代码味道,表明您的设计有点不对劲。 (有时你确实需要这样做,但它没有利用多态性)。
要利用多态性,您需要 Shape
将 displayShape()
定义为抽象方法,然后代替 drawCircle()
、drawSquare()
等...每个子类Shape
将有自己的 displayShape()
方法版本,而在 Shape
中你将拥有:
public abstract displayShape();
这是一种告诉编译器 "all my subclasses will have this displayShape() method so when someone calls displayShape() on one of me, use the one defined in that subclass".
的方式
例如:
Shape myCircle = new Circle();
Shape mySquare = new Square();
myCircle.displayShape(); //draws a circle
mySquare.displayShape(); //draws a square
//And if you can't choose which one you want...
Shape surpriseMe = new Random().nextBoolean() ? myCircle : mySquare;
surpriseMe.displayShape(); //draws either a circle or a square!
怎么样
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);
}
}
编译器只知道 myShape
是一个 Shape
类型的引用变量,它只包含一个方法 displayShape()
,所以根据编译器,调用是不可能的Shape
class 不包含的方法 drawCircle()
。
编译器不关心这个变量在运行时持有什么对象。您可以在稍后的某个时间点从 Shape
class 扩展另一个 class,并使用 myShape
引用来保存该子 class 对象。编译器只关心 myShape
在编译时是什么类型。
如果您的 Circle
class 碰巧覆盖了 displayShape()
方法,如下所示:
public class Circle extends Shape {
public void displayShape() {
System.out.println("I am a Circle!");
}
public void drawCircle() {
// Implementation here
}
}
在运行时发生的唯一决定是调用哪个 displayShape()
方法。
我知道,无论引用变量引用的实际对象是什么,我可以调用引用的方法取决于变量的声明类型(在代码的第 15 行)。我想知道为什么so.Why用户不能class使用Shape类型的引用变量s调用它的subclass方法drawCircle()?
public class Shape{
public void displayShape(){
System.out.println("shape displayed");
}
public class Circle extends Shape{
public void drawCircle(){
System.out.println("circle drawn");
}
public class Test{
p.s.v.main(String[] a){
Circle c=new Circle();
Shape s=new Shape();
display(c);
display(s);
public void display(Shape myShape){
myShape.displayShape();//possible for ref variable c and s
myShape.drawCircle();//not possible for reference var s
}
}
}
你能解释一下在对象级别发生了什么吗?我是 java 的新手。
首先,您忘记制作 Shape
的 Circle
subclass。
然后你说:
The methods i can call on a reference is dependent on the declared type of the variable
但是Shape myShape
参数也是一个变量:
public void display(Shape myShape){
...
myShape.drawCircle();
}
所以这里也是,对于局部变量或者字段变量,编译器只依赖声明的类型来绑定调用的方法。
由于 Shape
class 用作声明变量的类型,因此只能调用此 class 的方法。
如果您确定 myShape 是一个 Circle,您可以明确地将其转换为一个
((Circle)myShape).drawCircle();
或 Circle myCircle = (Circle)myShape; myCircle.drawCircle();
但如果你这样做并且它实际上不是 Circle
那么你将得到 ClassCastException
。
通常,您想尝试避免这种类型的转换,因为它有点代码味道,表明您的设计有点不对劲。 (有时你确实需要这样做,但它没有利用多态性)。
要利用多态性,您需要 Shape
将 displayShape()
定义为抽象方法,然后代替 drawCircle()
、drawSquare()
等...每个子类Shape
将有自己的 displayShape()
方法版本,而在 Shape
中你将拥有:
public abstract displayShape();
这是一种告诉编译器 "all my subclasses will have this displayShape() method so when someone calls displayShape() on one of me, use the one defined in that subclass".
例如:
Shape myCircle = new Circle();
Shape mySquare = new Square();
myCircle.displayShape(); //draws a circle
mySquare.displayShape(); //draws a square
//And if you can't choose which one you want...
Shape surpriseMe = new Random().nextBoolean() ? myCircle : mySquare;
surpriseMe.displayShape(); //draws either a circle or a square!
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);
}
}
编译器只知道 myShape
是一个 Shape
类型的引用变量,它只包含一个方法 displayShape()
,所以根据编译器,调用是不可能的Shape
class 不包含的方法 drawCircle()
。
编译器不关心这个变量在运行时持有什么对象。您可以在稍后的某个时间点从 Shape
class 扩展另一个 class,并使用 myShape
引用来保存该子 class 对象。编译器只关心 myShape
在编译时是什么类型。
如果您的 Circle
class 碰巧覆盖了 displayShape()
方法,如下所示:
public class Circle extends Shape {
public void displayShape() {
System.out.println("I am a Circle!");
}
public void drawCircle() {
// Implementation here
}
}
在运行时发生的唯一决定是调用哪个 displayShape()
方法。