【第五章 多态性、重载和重写、instanceof关键字】

第五章 多态性

1,面向对象特征之三:多态性
①可以理解为一个事物的多种形态;(运行时行为)
②对象的多态性:父类的引用指向子类的对象;或者子类的对象赋给父类的引用。
③多态的使用:虚拟方法调用(动态绑定)
有了对象的多态性以后,在编译期,只能调用父类中声明的方法,但在运行期,实际执行的是子类重写父类的方法。(编译看左边,运行看右边)
④多态性的使用前提:
a.类的继承关系;b.要有方法的重写。
⑤对象的多态性:只适用于方法,不适用于属性。(属性:编译和运行都看左边)
⑥虚拟方法调用(多态情况下):
子类中定义了于父类同名同参的方法,在多态情况下,将此时父类的方法称为虚拟方法,父类根据赋给它的不同的子类对象,动态调用属于子类的该方法,这样的方法调用在编译期是无法确定的。

public class PersonTest {
	public static void main(String[] args) {
		Person p1=new Person();
		p1.eat();
		Man man=new Man();
		man.eat();
		man.age=25;
		System.out.println();
		//********************
		//对象的多态性:父类的引用指向子类的对象。
		Person p2=new Man();
		//当调用子父类同名同参的方法时,实际执行的是子类重写父类的方法---虚拟方法调用。
		p2.eat();
		p2.walk();
		Person p3=new Woman();
	}
}
package day45;
public class AnimalTest {
	public static void main(String[] args) {
		AnimalTest test=new AnimalTest();
		test.func(new Dog());
		test.func(new Cat());
	}
	public void func(Animal animal) {
		animal.eat();
		animal.shout();
		System.out.println();
	}
}
class Animal{
	public void eat() {
		System.out.println("动物进食");
	}
	public void shout() {
		System.out.println("动物叫");}
}
class Dog extends Animal{
	public void eat() {
		System.out.println("狗进食");
	}
	public void shout() {
		System.out.println("汪汪汪");}
}
class Cat extends Animal{
	public void eat() {
		System.out.println("猫进食");
	}
	public void shout() {
		System.out.println("喵喵喵");}
}

2.重载和重写(重写就是多态性的体现)
(1)重载发生在同一个类中,若多个方法之间方法名相同、参数列表不同,则它们构成重载的关系。重载与方法的返回值以及访问修饰符无关,即重载的方法不能根据返回类型进行区分。
(2)重写发生在父类子类中,若子类方法想要和父类方法构成重写关系,则它的方法名、参数列表必须相同。另外,返回值要小于等于父类方法,抛出的异常要小于等于父类方法,访问修饰符则要大于等于父类方法。若父类方法的访问修饰符为private,则子类不能对其进行重写。
(3)从运行的角度看:
①重载:允许存在多个同名方法,这些方法参数不同,编译器根据方法的不同的参数列表,对同名方法做修饰,对于编译器而言,这些同名方法就成了不同的方法,它们调用地址在编译期就确定了,重载是可以包括父类和子类的,即子类可以重载父类的同名不同参数的方法。(早绑定或静态绑定)
②对于多态:只有等到方法调用的那一刻,解释运行器才会确定所要调用的具体方法。(晚绑定或动态绑定)
3.instanceof关键字的使用
①使用原因:有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法,但是由于变量声明为父类类型,导致编译时只能调用父类中声明的属性和方法,子类特有的属性和方法不能调用。
②如何调用子类特有的属性和方法?
(1)向下转型 使用强转时,可能出现ClassCastException;
(2) a instanceof A:判断对象a是否是类A的实例,如果是,返回true,否则,返回false;
(3)使用情景:为了避免在向下转型时出现ClassCastException的异常,我们在向下转型之前,先进行instanceof的判断,一旦返回true,就进行向下转型,如果返回false,不进行向下转型;
(4)如果 a instanceof A 返回true,则a instanceof B也返回true,其中,类B是类A的父类。

package day46;
/**
 *此前已有Man,Person,Woman类
 * @author 26312
 */
public class PersonTest {
	public static void main(String[] args) {
		Person p1=new Person();
		p1.eat();
		Man man=new Man();
		man.eat();
		man.age=25;
		System.out.println();
		//对象的多态性:父类的引用指向子类的对象。
		Person p2=new Man();
		p2.eat();
		p2.walk();
		Person p3=new Woman();
		//子类特有的属性和方法不能调用
		//p2.isSmoking="true";
		//如何调用子类特有的属性和方法?
		//向下转型 使用强转时,可能出现ClassCastException
		//错误,不进入,应该为p3
		if (p2 instanceof Woman) {
			Woman w1=(Woman)p2;
			w1.goShopping();
			System.out.println("woman");
		}
		//正确,可以进入if
		if (p2 instanceof Man) {
			Man m2=(Man)p2;
			m2.earnMoney();
			System.out.println("man");
		}
	}
}

4.子类继承父类(多态性)
①若子类重写了父类方法,就意味着子类里定义的方法彻底覆盖了父类里的同名方法,系统将不可能把父类里的方法转移到子类中;
②对于实例变量则不存在这样的现象,即使子类里定义了与父类完全相同的实例变量,这个实例变量依然不可能覆盖父类中定义的实例变量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值