【尚硅谷-Java学习】5.4 面向对象的特征之三 多态性

面向对象的三大特征:

  • 封装性、
  • 继承性、
  • 多态性、
  • (抽象性)

多态性

1.对象的多态性

  • 父类的引用 指向 子类的对象(或子类的对象赋给父类的引用)。
//例如有父类Person,子类Man、Woman。
Person p1 = new Man();
  • 调用子父类同名同参的方法时,实际执行的是子类重写的方法–虚拟方法调用

2.多态的使用:虚拟方法调用

  • 在编译期,只能调用父类所声明的方法,不能调用子类特有的方法。
  • 在运行期,实际执行的是子类重写的方法。此时父类方法称为虚拟方法。

总结:编译看左边,运行看右边。

3.对象的多态性只适用于方法,不适用于属性。

public class Test {
	public static void main(String[] args) {
		Person p1 = new Man();
		System.out.println(p1.id);//1001
	}
}

class Person{
	int id = 1001;
}
class Man extends Person{
	int id = 1002;
}

4.使用前提

  • 有类的继承关系
  • 子类重写父类的方法

5.应用

一、


public class AnimalTest {
	public static void main(String[] args) {
		AnimalTest at1 = new AnimalTest();
		at1.func(new Dog());
		at1.func(new Cat());
		
	}
	public void func(Animal animal){
		animal.eat();
	}
}

class Animal{
	public void  eat(){
		System.out.println("吃");
	}
}

class Cat extends Animal{
	public void  eat(){
		System.out.println("吃鱼");
	}
}

class Dog extends Animal{
	public void  eat(){
		System.out.println("吃骨头");
	}
}

有了多态性,一个func()方法就足够,否则需要写三个(func(Animal)、func(Dog)、func(Cat)

二、

public void method(Object obj){

}

创建的任何子类对象都能用method方法。例如equals()。

6.多态是运行时行为

在编译时对象是父类类型,在运行时根据赋予的不同子类对象,动态调用该子类的方法,称为动态绑定

7.多态性的实质:将子类转换成父类,也被称为向上转型

8.练习

练习(1)

有父类Base:

class Base{
	String name = "Base";
	public void display(){
		System.out.println(name);
	}
}

子类Sub:

class Sub extends Base{
	String name = "Sub";
	public void display(){
		System.out.println(name);
	}
}

语句1.

Sub s = new Sub();
System.out.println(s.name);

输出:Sub

语句2.

s.display();

输出:Sub

语句3. 多态的应用.

对于引用数据类型," == " 比较的是地址值。" = "将s的地址值赋给b,因此结果为true。

Base b = s;//多态
System.out.println(b == s);

输出:true

语句4. 多态的应用.

多态性不包含属性,调用属性时,编译运行都看左边:Base类

System.out.println(b.name);

输出:Base

语句5. 多态的应用.

调用方法时,编译看左边:Base。运行时看右边:即Sub类

b.display();

输出:Sub

练习(2)

有父类GeometricObject代表几何形状。
子类Circle圆形、MyRectangle矩形。定义了findArea()方法计算面积。
当使用多态性进行动态绑定(即调用虚拟方法)时,需要在父类添加方法findArea(),因无法确定具体形状,该方法返回0.0即可。

public class GeometricObject {
	//
	...
	//
	public double findArea(){
		return 0.0;
	}
}

练习(3)

有父类Base,子类Sub:

class Base{
	public void add(int a, int... arr){
		System.out.println(base);
	}
}
class Sub extends Base{
	public void add(int a, int[] arr){
		System.out.println(sub);
	}
}

运行语句:

Base b = New Sub();
b.add(1,2,3);

关键点在于:int… 与 int[ ]是否看作同一参数。是的话子类对add方法进行重写,多态后b调用的是子类方法,输出“sub”。否则add(int a, int[] arr)是子类特有的方法,b无法调用。
答案是:int… 与 int[ ] 看作同一参数

练习(3)进阶

在子类Sub中添加方法add

class Sub extends Base{
	public void add(int a, int[] arr){
		System.out.println(sub);
	}
	public void add(int a,int b,int c){
		System.out.println(sub_2);
	}
}

add(int a,int b,int c)是子类特有的方法,多态后,通过b只能调用子类的add(int a, int[] arr),输出为“sub”。

练习(3)进阶之进阶

运行语句

Sub s = (Sub)b;
s.add(1,2,3);

不确定参数的add(int a, int[] arr)与确定参数的add(int a,int b,int c),优先调用确定参数的方法。输出“sub_2”

你可能感兴趣的:(【尚硅谷-Java学习】)