多态中父类的等价写法

一.多态的三个条件

 1.继承 2.子类重写父类方法 3.父类引用指向子类对像

二.继承的等价写法

父类,子类定义如下:

		class Father{
		    void test()
			{
				System.out.println("Father test");	
			}
		}
		class Son extends Father{

			void test2()
			{
				System.out.println("Son test2");
				
			}			
		}

子类Son继承了父类Father,并且Son有了自己的方法test2,则Son的等价写法如下:

		class Son {//此处去掉了继承Father,  
                            //此Son的等价写法,是为了说明继承后,子类Son中都有什么方法可用
			void test()
			{
				System.out.println("Father test");	
			}
			void test2()
			{
				System.out.println("Son test2");	
			}			
		}

Son的等价写法不难理解,这样写,是为了引出多态中父类的等价写法,这样,可以更明确的知道,父类都有什么方法可以调用

三.多态的等价写法

父类,子类的定义如下,子类重写了父类的方法:

		class Father{
			void test()
			{
				System.out.println("Father test");	
			}
			void test2()
			{
				System.out.println("Father test2");	
			}
		}
		class Son extends Father{
			void test()
			{
				System.out.println("Son test");	
			}	
			void test3()
			{
				System.out.println("Son test3");	
			}	
		}

父类中有test()和test2()两个方法,子类中重写了父类的test()方法,添加了自己的方法test3()

调用:Father fa=new Son();     fa.test();

                输出:Son test

继承,重写test(),父类指向子类对象,形成多态,输出“Son test”


A. 那么多态情况下,父类的等价写法,如下:

		class Father{
			void test()//多态子类重写的test()覆盖了父类的方法test()
			{
				System.out.println("Son test");	
			}
			void test2()
			{
				System.out.println("Father test2");	
			}
		}

这就相当于,在形成多态的情况下,父类中的方法,被子类中的重写的方法被覆盖

特别说明下:这个只是多态下,父类的等价写法而已,并不是父类的真实代码,多态是在运行的时候动态调用的子类的重写方法,编译的时候,父类还是原来的代码。

多态下父类的等价写法,可以这样理解:相当于,多态下,子类的方法上行传递给了父类,覆盖了父类的代码

也就是,子类重写的方法,test()覆盖了父类的方法test()


可以和继承做个比较,继承是父类方法,下行,传递给了子类

B.同一代码,继续时候,子类的等价代码如下:

		class Son {
			void test()//子类重写的方法,覆盖了父类方法
			{
				System.out.println("Son test");	
			}	
			void test2()//子类继承的父类方法test2
			{
				System.out.println("Father test2");	
			}
			void test3()//子类自己定义的自己特有的方法,跟父类一毛钱关系都没有
			{
				System.out.println("Son test3");	
			}	
		}

之所以,改写为等价写法,是把子类和父类,拆了两个独立的没关系的个体。这样,可以明确知道,实例对象,调用的是哪个方法。

三.小结

1.多态下,父类的等价写法,可以看成,子类方法上行传递覆盖了父类的方法。

2.继承的等价写法,可以看出,父类方法下行传递给了子类方法。

3.拆成了等价写法,可以看成父类子类是两个没关系的独立的类,可以方便的看出,对象指向的是哪个类,就明确了,方法的内容。

四.举个栗子

有如下三个类,继承关系如下:

class ClassA{
	void show(){
		show2();
	}
	void show2(){
		System.out.println("ClassA show2");
	}
}
class ClassB extends ClassA{
	void show2(){
		System.out.println("ClassB show2");
	}
}
class ClassC extends ClassB{
	void show()
	{
		super.show();
	}
	void show2(){
		System.out.println("ClassC show2");
	}
}

测试代码:ClassB b=new ClassC();     b.show();

1. b指向子类ClassC的对象,调用的是ClassC里的 show()

2. ClassC里show(),调用super.show(),这里super指向ClassB的父类ClassA的对象

3.调用了从ClassA里面继承过来的show()方法

4.ClassB的show()方法调用 show2()

到这里问题来了,到底应该调用哪个类里的show2()方法呢?

先绕个弯分析一下,哪个方法符合多态

1.show方法是否有多态

  •     ClassB继承了ClassA,没有重写show(),所以此处没有多态
  •     ClassC继承了ClassB,重写了show(),可以形成多态

2.show2()的多态情况

  • ClassB继承了ClassA,重写了show2(),可以形成多态
  • ClassC继承了ClassB,重写了show2(),可以形成多态

可以看出,show2()形成了多态,所以最终,都是调用的ClassC中重写的show2()
所以,输出为:ClassC show2

以下,看下等价类分析结果:

ClassA,ClassB,ClassC在多态情况下的等价写法,也包括继承的等价写法:

class ClassA{
	void show(){
		show2();
	}
	void show2(){
		System.out.println("ClassC show2");
	}
}
class ClassB {
	void show()
	{
		super.show();
	}
	void show2(){
		System.out.println("ClassC show2");
	}
}

class ClassC {
	void show()
	{
		super.show();
	}
	void show2(){
		System.out.println("ClassC show2");
	}
}
这样把三个类看成三个独立的类,可以看出 各自的对象可以调用哪些方法:(由于,看成独立的类,super得单独指向父类)

CalssC:重写了ClassB的show(),和show2()

ClassB: ClassB的继承的show()和自己的show2()由于形成重写,被子类CalssC重写的方法覆盖

ClassA:ClassB中没有重写show(),未形成多态,所以,ClassA仍是原来自己的show()

            ClassB中重写了show2(),形成多态,所以,上行覆盖ClassA的show2()

            而CalssC又重写了ClassB的show2(),形成多态,所以,上行传递,覆盖了ClassA和ClassB的show2()

这样,可以从三个等价类,看出 b.show()可以调用过程。

1. b.show()调用了super.show()

2.super.show()指向了ClassA的show()

3.ClassA的show()调用了ClassA的show2()

输出为:ClassC show2


猜你喜欢

转载自blog.csdn.net/kangyouv/article/details/80983063
今日推荐