java_面向对象_多态_11

多态:同一个对象(事物),在不同时刻体现出来的不同状态。
例:猫是猫,猫是动物。 水(液体,固体,气态)。	

1.多态的好处:
A:提高了代码的维护性(继承保证)
B:提高了代码的扩展性(由多态保证)
	

对象间的转型问题:
	向上转型:从子到父
		Fu f = new Zi();
	向下转型:从父到子
		Zi z = (Zi)f;  

1.多态的前提

1.继承
2.要有方法重写(相同方法)
3.父类应用指向子类对象 父 f = new 子();

class Fu{
	public void show(){
		System.out.println(show Fu);
	}
}
class Son extends Fu{  //继承是多态的前提
	public void show(){  //重写父类方法
		System.out.println(show son); 
	}
}
class DuotaiDemo{
	public static void main(String[] args){
		Fu f  = new Son(); //父类引用指向自类对象。
	}
}

2.多态中成员访问特点

f.show();
编译的时候都要看父类中有没有相关的成员变量,成员方法,静态方法,没有会报错;出现被重写的成员方法时,运行的结果就是子类中的内容。

1.成员变量
	[编译看左边,运行看左边。]
	父类引用只能访问父类成员变量。
2.构造方法
	创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化。
3.成员方法
	 [编译看左边,运行看右边。]
	 父类引用
	 只有被方法重写了之后,运行才是子类中的内容;成员变量没有重写,静态方法和类相关,算不上重写,所以都是访问左边。
4.静态方法
	编译看左边,运行看左边。
	(静态和类相关,算不上重写,所以,访问还是左边的)
			
由于成员方法存在方法重写,所以它运行看右边。		
  • 多态的 成员方法,成员变量
    由于多态的成员比哪里和和成员方法存在编译看左边,运行看右边的特性,所以使用多态来访问的成员变量和成员方法都必须要重写父类的(也就是父类和子类中都有相同的成员变量和成员方法)。
    这个也是多态的弊端不能使用子类的特有功能。
    在这里插入图片描述
3.多态的扩展性体现:

被延续的代码:

class Animal {
	public void eat(){ System.out.println("eat"); }	
	public void sleep(){ System.out.println("sleep" ); }
}
//第一只动物,子类
class Dog extends Animal { //子类继承父类
	//子类重写父类方法
	public void eat(){ System.out.println("狗吃肉"); }
	public void sleep(){ System.out.println("狗站着睡觉"); }
}
//扩展第二只动物。。。。。。。。。
class Cat extends Animal { 
	public void eat() { System.out.println("猫吃鱼"); }
	public void sleep() { System.out.println("猫趴着睡觉"); }
}
//扩展第n只动物......
  • 没有使用多态的普通版。
.....  延续上面的
//针对动物操作的工具类,工具类不建议修改。帮助子类对象更加方便的调用子类方法。
class AnimalTool {
	private AnimalTool(){}  //私有无参构造方法,使类不能创建对象
	
	public static void useCat(Cat c) {  //静态方法,不创建对象,直接用类进行调用。
		c.eat();
		c.sleep();
	}
	//扩展第二只动物的操作方法。。。。。
	public static void useDog(Dog d) { d.eat(); d.sleep(); }
	//扩展第n只动物的操作方法.........。。。。
}

//测试类。
class DuoTaiDemo2 {
	public static void main(String[] args) {
		Cat c = new Cat();
		Cat c2 = new Cat();
		AnimalTool.useCat(c);
		AnimalTool.useCat(c2);
	
		
		Dog d = new Dog();
		Dog d2 = new Dog();
		AnimalTool.useDog(d);
		AnimalTool.useDog(d2);
	}
}

从上面这些代码可以看出,当子类不断增加的时候,导致操作子类的工具类也在不断添加新的子类操作方法,但是工具类是操作子类方法的,所以不建议频繁修改,

  • 多态 [扩展性]
class AnimalTool {
	private AnimalTool(){}  //使类不能创建对象
	public static void useAnimal(Animal a) {  //传入父类引用
		a.eat();
		a.sleep();
	}
}

class DuoTaiDemo2 {
	public static void main(String[] args) {
		Cat c = new Cat();
		Cat c2 = new Cat();
		AnimalTool.useAnimal(c);  //子类引用等于父类引用,实现了多态的要求。
		AnimalTool.useAnimal(c2);
			
		Dog d = new Dog();
		Dog d2 = new Dog();
		AnimalTool.useAnimal(d);
		AnimalTool.useAnimal(d2);
}

4.多态的弊端:

  • 不能使用子类特有的功能:
class Fu{
	public void show(){ System.out.println("show Fu"); }
}
class Zi extends Fu{
	public void show(){ System.out.println("show zi"); }
	public void method(){ System.out.println("show zi method");}
}
//延续代码001
class DuotaiDemo{
	public static void main(String[] args){
		Fu f = new Zi();
		f.show(); 
		f.method();  //报错,不能使用子类中的特有功能。
	}
}
  • 向下转型使用子类特有功能。
//.....延续代码001

class DuotaiDemo{
	public static void main(String[] args){
		Fu f = new Zi();
		Zi z = (Zi)f;  //Zi z = f 表示把父的引用赋值值给子的引用。使用(Zi)进行强转。
		f.show();
		z.method();  //可以使用子类特有功能。
	}
}

没使用向下转型之前,父类的引用指向子类对象,编译时父所调用的方法必须在父类中存在(子类中重写),否则会报错。
使用向下转型之后,将父类的引用强制转换为子类的引用,此时编译的时候,子类调用的方法只需要在子类中存在即可,实现向下转型使用子类特有功能。
在这里插入图片描述

5.多态的转型问题

Java培训特别火,很多人来请孔子爹去讲课,这一天孔子爹被请走了,但是还有人来请,就剩孔子在家,价格还挺高。孔子一想,然后就穿上爹的衣服,带上爹的眼睛,粘上爹的胡子。就开始装爹

	class 孔子爹 {
		public int age = 40;
		public void teach() {
			System.out.println("讲解JavaSE");
		}
	}
	
	class 孔子 extends 孔子爹 {
		public int age = 20;
		public void teach() {
			System.out.println("讲解论语");
		}
		public void playGame() {
			System.out.println("英雄联盟");
		}
	}
	
	//向上转型
	孔子爹 k爹 = new 孔子();  //孔子看穿着爹的衣服,看起来像爹。
			//到人家那里去了
	System.out.println(k爹.age); //40 外表看起来就是爹的年龄
	k爹.teach(); //虽然长得像爹,但是他只会讲解论语
	//k爹.playGame();  由于长得想爹,所以虽然本质上是儿子,但是也不能使用儿子的功能。
	
	//向下转型	
	孔子 k = (孔子) k爹;  //讲完了,下班回家了,脱下爹的装备,换上自己的装备
	System.out.println(k.age); //现在看起来年级就是20
	k.teach(); //他在做他自己,所以讲解论语
	k.playGame(); //所以也能玩游戏英雄联盟
	

6.多态练习:

  • 不同地方饮食文化不同的案例
class Person {
	public void eat() { System.out.println("吃饭"); }
}
class SouthPerson extends Person {
	public void eat() {	System.out.println("炒菜,吃米饭"); }
	public void jingShang() { System.out.println("经商"); }
}
class NorthPerson extends Person {
	public void eat() { System.out.println("炖菜,吃馒头"); }
	public void yanJiu() { System.out.println("研究"); }
}

class DuoTaiTest2 {
	public static void main(String[] args) {
		
		Person p = new SouthPerson(); //南方人
		p.eat();
		SouthPerson sp = (SouthPerson)p;
		sp.jingShang();
		
		p = new NorthPerson(); //北方人
		p.eat();
		NorthPerson np = (NorthPerson)p;
		np.yanJiu();
	}
}
  • 猫狗练习
class Animal {
	public void eat(){	System.out.println("吃饭"); } 
	}
class Dog extends Animal {
	public void eat() { System.out.println("狗吃肉"); }
	public void lookDoor() { System.out.println("狗看门"); }
}
class Cat extends Animal {
	public void eat() { System.out.println("猫吃鱼"); }
	public void playGame() { System.out.println("猫捉迷藏"); }
}
class DuoTaiTest {
	public static void main(String[] args) {
		//定义为狗
		Animal a = new Dog();
		a.eat();
		//还原成狗
		Dog d = (Dog)a;
		d.eat();
		d.lookDoor();
		
		//变成猫
		a = new Cat(); //重点:可以直接赋值
		a.eat();
		//还原成猫
		Cat c = (Cat)a;
		c.eat();
		c.playGame();
	
		//编译不报错,运行时候报错。此时不能再强制转换了,因为此时a是猫的引用,所以不能强制转换为狗的引用。
		//Dog dd = (Dog)a;
	}
}	
  • 多态的一个综合案例
    继承的时候:
    子类中有和父类中一样的方法,叫重写。
    子类中没有父亲中出现过的方法,方法就被继承过来了。
class A {
        public void show() { show2(); }
        public void show2() { System.out.println("我");}
}
class B extends A {
        /*  public void show() {  show2();  }  */
        public void show2() { System.out.println("爱"); }
}
class C extends B {
        public void show() {  super.show();  }
        public void show2() { System.out.println("你"); }
}
class DuoTai {
        public static void main(String[] args) {
                A a = new B();
                a.show(); //子类没有,继承父类show方法,此时继承过来的show方法中调用的show2方法就是B中的show2方法。

                B b = new C();
                b.show(); //子类c覆盖(重写)父类B的show方法,通过super.show()调用父类show方法,父类的show方法中调用的是show2方法,此时show2方法就是C中的show2。
        }
}

  • no
/*
	ClassCastException:类型转换异常
	一般在多态的向下转型中容易出现
*/
class Animal { public void eat(){} }
class Dog extends Animal {
	public void eat() {}
	public void lookDoor() {
	
	}
}
class Cat extends Animal {
	public void eat() {
	
	}
	
	public void playGame() {
		
	}
}

class DuoTaiDemo5 {
	public static void main(String[] args) {
		//内存中的是狗
		Animal a = new Dog();
		Dog d = (Dog)a;
		
		//内存中是猫
		a = new Cat();
		Cat c = (Cat)a;
		
		//内存中是猫
		Dog dd = (Dog)a; //ClassCastException
	}
}
发布了80 篇原创文章 · 获赞 0 · 访问量 1740

猜你喜欢

转载自blog.csdn.net/weixin_41272269/article/details/103645288