参考大神博客:
http://www.cnblogs.com/chenssy/p/3372798.html
1 多态,编译时的类型和运行时的类型不一致,当运行时调用该引用变量的方法时,其总是表现出子类方法的行为特征,而不是父类方法的行为特征,这就可能出现,相同类型的变量,调用其中的方法时呈现出多种不同的行为特征。
例:
class BaseClass{
public int book=6;
public void base(){
System.out.println("BaseClass:base");
}
public void test(){
System.out.println("BaseClass:test()");
}
}
class SubClass extends BaseClass{
//重新定义一个变量
public String book="子类中定义的变量";
//子类覆盖父类的方法
public void test(){
System.out.println("SubClass:text()");
}
//子类中定义的普通方法
public void sub(){
System.out.println("SubClass:sub");
}
}
public class TextDemo_14 {
public static void main(String[] args) {
// TODO Auto-generated method stub
BaseClass text=new SubClass();
System.out.println(text.book);//重写父类的变量,还是返回的是父类中的变量
text.base();//子类无重写该方法,执行的是父类中base方法
text.test();//重写父类的方法,执行的是子类的test方法,即重写后的方法
//text.sub();指向父类的变量无法访问子类的中的方法,打开编译时显示错误
}
}
2 多态:
在继承中我们知道子类是父类的扩展,它可以提供比父类更加强大的功能,如果我们定义了一个指向子类的父类引用类型,那么它除了能够引用父类的共性外,还可以使用子类强大的功能。
比如你是一个酒神,对酒情有独钟。某日回家发现桌上有几个杯子里面都装了白酒,从外面看我们是不可能知道这是些什么酒,只有喝了之后才能够猜出来是何种酒。你一喝,这是剑南春、再喝这是五粮液、再喝这是酒鬼酒….在这里我们可以描述成如下:
酒 a = 剑南春
酒 b = 五粮液
酒 c = 酒鬼酒
…
这里所表现的的就是多态。剑南春、五粮液、酒鬼酒都是酒的子类,我们只是通过酒这一个父类就能够引用不同的子类,这就是多态——我们只有在运行的时候才会知道引用变量所指向的具体实例对象。
向上转型存在一些缺憾,那就是它必定会导致一些方法和属性的丢失,而导致我们不能够获取它们。所以父类类型的引用可以调用父类中定义的所有属性和方法,对于只存在与子类中的方法和属性它就望尘莫及了
总结:
指向子类的父类引用由于向上转型了,它只能访问父类中拥有的方法和属性,而对于子类中存在而父类中不存在的方法,该引用是不能使用的,尽管是重载该方法。若子类重写了父类中的某些方法,在调用该些方法的时候,必定是使用子类中定义的这些方法(动态连接、动态调用)。
class A {
public String show(D obj) {
return ("A and D");
}
public String show(A obj) {
return ("A and A");
}
}
class B extends A {
public String show(B obj) {
return ("B and B");
}
public String show(A obj) {
return ("B and A");
}
}
class C extends B {
}
class D extends B {
}
public class TextDemo_14 {
public static void main(String[] args) {
A a1 = new A();
A a2 = new B();
B b = new B();
C c = new C();
D d = new D();
System.out.println("4--" + a2.show(b));// B and A
// 推理过程----》
// 先在父类A中看找到该方法,因为C类继承自A和B,在A中有一个方法中的参数即是C类的父类可以匹配到,
// 看在B类中重写了该方法,即执行该方法
System.out.println("5--" + a2.show(c));// B and A
System.out.println("6--" + a2.show(d));// A and D
System.out.println("7--" + b.show(b));// B and B
System.out.println("8--" + b.show(c));// B and B
System.out.println("9--" + b.show(d));// A and D
}
}
总结:
当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法,但是它仍然要根据继承链中方法调用的优先级来确认方法,该优先级为:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。
未完待续。。。