假使,父类为 :Parent 子类为:Son则会有下面的情况:
Parent p = new Son();
那么这个只能调用父类是的方法,如果子类Son有重写这些方法,就会调用Son中重写父类的方法。 有了这个前提,问题来了:
这里有一个方法传入的参数是父类(Parent),那么也可以传入它的子类Son。因为可以这样转换 Parent p = new Son();
public void test(Parent p){……} 但是传入Son时,为什么可以调用son自己特有的方法,而是不前一种情况:只调用子类中重写父类的法。
这里我只能理解前一种情况,后一种不知道该怎么理解。
Parent p = new Son();
那么这个只能调用父类是的方法,如果子类Son有重写这些方法,就会调用Son中重写父类的方法。 有了这个前提,问题来了:
这里有一个方法传入的参数是父类(Parent),那么也可以传入它的子类Son。因为可以这样转换 Parent p = new Son();
public void test(Parent p){……} 但是传入Son时,为什么可以调用son自己特有的方法,而是不前一种情况:只调用子类中重写父类的法。
这里我只能理解前一种情况,后一种不知道该怎么理解。
public static void main(String[] args) {
Parent parent = new Son();
parent.a();
test(parent);
Son son = new Son();
son.a();
test(son);
} static void test(Parent p) {
p.a();
// error
// p.b();
if (p instanceof Son) {
((Son) p).b();
}
}
}class Parent {
public void a() {
System.out.println("pa");
}
}class Son extends Parent {
@Override
public void a() {
System.out.println("sa");
} public void b() {
System.out.println("sb");
}
}
动态绑定
后期绑定:在运行时根据具体对象的类型进行绑定。
若一种语言实现了后期绑定,同时必须提供一些机制,可在运行期间判断对象的类型,并分别调用适当的方法。也就是说,编译器此时依然不知道对象的类型,但方法调用机制能自己去调查,找到正确的方法主体。不同的语言对后期绑定的实现方法是有所区别的。但我们至少可以这样认为:它们都要在对象中安插某些特殊类型的信息。
动态绑定的过程:
虚拟机提取对象的实际类型的方法表;
虚拟机搜索方法签名;
调用方法。
Parent p = new Son();
这个p不能调用son的特有方法,所以也就是说“new的是son 自然是可以调用son的所有方法了”,是不成立的例如public class test2 { /**
* @param args
*/
public static void main(String[] args) {
/**
* 为了测试当new出一个子类,是否同时new它的父类,并且它们的顺序是怎么样的
*/
// Son s = new Son();
/**
* 显示结果为:
* parent构造方法
*son构造方法
*
*说明:实现子类的同时会实现它的父类,顺序是 父类-->子类
*/
// Parent p = new Son();
// p.method();
// p.parentMethod();
/**
* 显示结果为:
* parent构造方法
*son构造方法
*son_method
*parent的方法
*
*而且这个p不能调用son的特有方法sonMethod()
*/
Son s = new Son();
test2.test(s);
}
public static void test(Parent p){
p.method();
p.parentMethod();
}
}class Parent{
public Parent(){
System.out.println("parent构造方法");
}
public void method(){
System.out.println("parent_method");
}
public void parentMethod(){
System.out.println("parent的方法");
}
}class Son extends Parent{
public Son(){
System.out.println("son构造方法");
}
@Override
public void method() {
System.out.println("son_method");
}
public void sonMethod(){
System.out.println("son的方法");
}
}
不好意思,我是楼主……我特意来道歉的,szx_zsx 的说法是完全正解的,是我没有理解清楚 继承与多态。
这个我再仔细一想,我理解的才是正确的。
Parent p = new Son();
对象p 只能调用son中重写Parent的方法和继承自Parent但没有重写的方法,但是不能调用Son自己特有的方法sonMethod()
这里举一个生动的例子:
一个老铁匠还有一个他的儿子小铁匠,老铁匠使用的是传统工艺的打铁方法(daMethod()),他儿子从父亲那里学会打铁(也就是重写 daMethod()),但是小铁匠的是个21世纪的新青年不喜欢用传统方法打铁(嫌累)于是他用机器打铁,而且这个小铁匠的接收能力比较强,又学会的其它的技能。
public void test(Parent p){……} 这个怎么可能可以调用子类扩展的方法呢?除非你做向下转型 不过向下转型是不安全的 违反了里氏代换原则
可能吗?如果向下造型,也和前面的情形一样。
谢谢各位的耐心解答,自己也仔细的思考了,确实传入子类是不能调用它自己的特有方法,也就是等同于
Parent p = new Son();…………1
将p作为参数传入,也是等同
Son s = new Son();…………2
将s作为参数传入。
其效果是一样的……首先检测子类中是否有重写的方法,如果没有就会调用父类中的方法(继承)。而这里是不会调用到子类特有的方法的(除非使用三楼 zyc13701469860 所提到的判定条件 “p instanceof Son” 说明:传入的参数p是否是Son类的实例 也就是说1和2都是Son类的实例 ,但是3却却不是,那么条件判断是false )。1的说明:就是Parent父类给出了一个模板p,而new出来的Son不管它有多少自己特有的方法,但是都得往这个模板去靠,也就是说不符合这个模板的(son的特有方法)就会被屏蔽掉。而2做为参数传入时,也是向这个定义的模板去靠拢(1是作为参数前就已经屏蔽掉了,而2是传入时才做屏蔽掉的)在此谢谢zyc13701469860 szx_zsx chengxu2011 huage1998 yqj2065 hhwyyda 各位的帮助!!!你们的回答对我很有用处