Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java访谈后的反思:继承和多态性_Java_Inheritance_Polymorphism - Fatal编程技术网

Java访谈后的反思:继承和多态性

Java访谈后的反思:继承和多态性,java,inheritance,polymorphism,Java,Inheritance,Polymorphism,以下代码: class Base{} class Agg extends Base{ public String getFields(){ String name="Agg"; return name; } } public class Avf{ public static void main(String args[]){ Base a=new Agg(); //please take a look here System.out.pr

以下代码:

class Base{}

class Agg extends Base{

   public String getFields(){
    String name="Agg";
    return name;
   }
}

public class Avf{
   public static void main(String args[]){
   Base a=new Agg();
   //please take a look here
   System.out.println(((Agg)a).getFields());  // why a needs cast to Agg? 

  }
}
我的问题是:为什么我们不能将
((Agg)a).getFields()
替换为
a.getFields()
?为什么我们需要在
a
上键入cast?我提到
getFields()
没有在类
Base
中定义,因此类
Agg
没有从其基类扩展此方法。但如果我在类
Base
中定义了方法
getFields(),
比如:

一切都会好的。然后 ((Agg)a).getFields()等同于a.getFields()

在代码中

Base a=new Agg();    
此行是否意味着
a
引用了
Agg()
,并且a可以直接调用class
Agg
的方法。但是如果我不在类
Base
中定义方法
getFields()
,为什么会有区别呢?谁能给我解释一下吗

System.out.println(((Agg)a.getFields());//为什么a需要转换为Agg?

因为
Base
没有名为
getFields
的方法

宣言

Base a;
…告诉编译器在使用
a
时要使用的接口。然后分配
newagg()并不重要
对于它,您必须
a
的界面仍然是
Base
。由于
Base
没有
getFields
,因此尝试使用
getFields
是一个编译错误

Base a=new Agg()

此行是否意味着
a
引用了
Agg()
,并且a可以直接调用class
Agg
的方法

这意味着
a
包含对
Agg
对象的引用,但是该对象的接口是由
Base
定义的,而不是
Agg
,因此如果
Agg
方法不是由
Base
定义的,则不能对其调用
Agg
方法(没有强制转换,强制转换是危险的,应该尽可能避免)

如果代码需要访问由
Agg
定义的方法或字段,那么变量(或参数,在我的示例中)应该声明为
Agg a
,而不是
Base a

这是OOP的基本原理,尤其是Java中的OOP实现:对象的接口和对象的实现之间有很大的区别。在您的示例中,您知道基础A < /C> >实际上是<代码> AGG,但请考虑如下:

void foo(Base a) {
    // Use `a` here...
}

// A long time later in a class far, far away...
xyz.foo(new Agg());
显然,在这里,编译器不应该允许您在
a
上使用未由
Base
定义的方法或字段。代码中的情况也一样,只是不太明显

System.out.println(((Agg)a.getFields());//为什么a需要转换为Agg?

因为
Base
没有名为
getFields
的方法

宣言

Base a;
…告诉编译器在使用
a
时要使用的接口。然后分配
newagg()并不重要
对于它,您必须
a
的界面仍然是
Base
。由于
Base
没有
getFields
,因此尝试使用
getFields
是一个编译错误

Base a=new Agg()

此行是否意味着
a
引用了
Agg()
,并且a可以直接调用class
Agg
的方法

这意味着
a
包含对
Agg
对象的引用,但是该对象的接口是由
Base
定义的,而不是
Agg
,因此如果
Agg
方法不是由
Base
定义的,则不能对其调用
Agg
方法(没有强制转换,强制转换是危险的,应该尽可能避免)

如果代码需要访问由
Agg
定义的方法或字段,那么变量(或参数,在我的示例中)应该声明为
Agg a
,而不是
Base a

这是OOP的基本原理,尤其是Java中的OOP实现:对象的接口和对象的实现之间有很大的区别。在您的示例中,您知道基础A < /C> >实际上是<代码> AGG,但请考虑如下:

void foo(Base a) {
    // Use `a` here...
}

// A long time later in a class far, far away...
xyz.foo(new Agg());
显然,在这里,编译器不应该允许您在
a
上使用未由
Base
定义的方法或字段。代码中的情况也一样,只是不太明显

我的问题是:为什么我们不能将((Agg)a.getFields()替换为a.getFields()?为什么我们需要在一个屏幕上打字

听起来您真的理解了这一点-编译器在编译时类型
a
(即
Base
)上找不到
getFields
方法,因此它会引发编译时错误

这似乎是问题的真正含义:

 Base a=new Agg();
此行是否意味着a具有Agg()的引用,并且a可以直接调用类Agg的方法。但如果我不在基类中定义getFields()方法,为什么会有区别呢?谁能给我解释一下吗

这意味着编译器只允许您访问
Base
的成员,因为它只知道这些成员是可用的。如果有多个方法具有相同的名称,则重载解析也将应用于编译时类型

但是,在执行时,您实际上是在调用类型为
Agg
的对象上的方法-因此,如果
Agg
覆盖在
Base
中声明的方法,则将使用
Agg
中的实现

基本上,您需要区分在编译时根据表达式的编译时类型做出的决策和(由JVM)在执行时根据值引用的对象的执行时类型做出的决策

我的问题是:为什么我们不能将((Agg)a.getFields()替换为a.getFields()?为什么我们需要在一个屏幕上打字

它变臭了