多态

**注意事项:

**多态特性,只体现在成员方法上。

**对于成员变量,不具备多态性。只看引用变量所属的类。

 

多态的前提:

需要存在继承或者实现关系

要有覆盖操作

 

1.多态:

子类对象的多种父类形态

父类类型的引用变量指向多种不同的子类对象

 

本态:子类对象的本类形态

 

** 多态引用:子类对象赋值于父类类型的引用变量

本态引用:子类对象赋值于子类类型的引用变量

 

2.虚方法调用:

**虚拟方法调用(Virtual Method Invocation) : 多态引用调用覆盖方法

1)编译期检查父类类型

2)运行期执行子类类型

 

举例:

父类对象Person 有say()方法 (比如Person say()方法打印这是一个人)

子类对象继承,并重写了say()方法。 (比如Chinese say()方法打印这是一个中国人)

这时 Person p = new Chinese ();

p.say(); //在运行时看new的对象实体, 动态绑定

调用 p.say() 方法,就属于虚方法调用,只需要看new的是什么对象,是子类对象就打印子类方法。

父类的say方法也得有,不然编译会报错(也就是编译期检查父类类型)

运行时,还是看new的是子类对象,就打印子类say方法 (也就是运行期执行子类类型)

**此时父类里面的say() 方法 ,就是虚拟方法,唯一的作用就是让编译通过。

 

多态副作用:多态引用时, 子类特有的成员不能访问, 多态副作用. 只能访问父类与子类共有的方法。

举例:子类有test()方法,父类没有。这时如果用 p.test() 来调用,就会直接编译报错。因为父类没有这个方法。

 

多态的应用一:

多态数组,可以保存任意本类及子类对象

举例:比如要创建一个对象数组,能放下chinese,american两个类型。那就可以创建一个Person父类,让chinese,american作为子类继承。再创建 Person[] 数组,那么两种类型的子类对象都能加入了。

多态应用二:在方法传参时,使用父类引用。在调用该方法时可以传递子类对象,实现传参的多态。

 

子类继承父类:

--若子类重写了父类方法,则意味着子类中定义的方法,彻底覆盖了父类中的同名方法,系统将不可能把父类中的方法,转移到子类中。

--对于实例变量,则不存在这样的现象。即使子类中定义了与父类完全相同的实例变量,这个实例变量依然不可能覆盖父类中定义的实例变量。

 

 

属性无多态性,方法才具备多态性,例子:


class Base {
	int count = 10;

	public void display() {
		System.out.println(this.count);
	}
}

class Sub extends Base {
	int count = 20;

	public void display() {
		System.out.println(this.count);
	}
}

public class TestFieldMethod {
	public static void main(String[] args) {
		Sub s = new Sub(); // 本态引用
		System.out.println(s.count); // 20
		s.display(); // 20
		
		Base b = s; // 多态引用
		System.out.println(b == s); // true
		System.out.println(b.count); // 10
		b.display(); //已重写的方法,子类对象父类引用,所以是20
	}
}

关于多态参数的方法,在调用后需要使用子类特殊方法时的处理方式 - 造型处理: instanceof

package com.atguigu.javase.inheritence;

class Base {
	int count = 10;

	public void display() {
		System.out.println(this.count);
	}
}

class Sub extends Base {
	int count = 20;

	public void display() {
		System.out.println(this.count);
	}
}

public class TestFieldMethod {
	public static void main(String[] args) {
		Sub s = new Sub(); // 本态引用
		System.out.println(s.count); // 20
		s.display(); // 20
		
		Base b = s; // 多态引用
		System.out.println(b == s); // true
		System.out.println(b.count); // 10
		b.display(); //已重写的方法,子类对象父类引用,所以是20
	}
}



关于多态参数的方法,在调用后需要使用子类特殊方法时的处理方式 - 造型处理: instanceof 
	public static void test(Person p) { // 多态参数方法
		p.sayHello();
		
		//p.spring();
		//if (是中国人) { 
		// 造型有风险, 需要先判断..
		// 对于对象类型的判断顺序应该先从子到父
		if (p instanceof Chinese) { // 判断p引用指向的对象实体是否是右侧Chinese类型的一个实例
			Chinese c = (Chinese)p; // 造型
			c.spring(); //想使用子类特有方法
		} else if (p instanceof American) {
			((American)p).thanksGiving(); // .号优先级最高, 所以需要()
		} else {
			System.out.println("普通人一个");
		}
	}
	
	public static void main(String[] args) {
		Chinese ch = new Chinese("李四", 40, "女", "牛");
		American am = new American("Jack", 35, "male", true);
		Person p = new Person("某人", 30, "未知");
		
		test(ch);
           test(am);
          test(p);
	}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值