多态

多态

多态基本介绍

多态:多种状态

方法或对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承基础之上的。

具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态。

多态实现条件

在java中要实现多态,必须要满足如下几个条件,缺一不可:

  1. 必须在继承体系下

  2. 子类必须要对父类中方法进行重写

  3. 通过父类的引用调用重写的方法

多态体现:在代码运行时,当传递不同类对象时,会调用对应类中的方法。

在这里插入图片描述

重写

重写(override):也称为覆盖。重写是子类对父类非静态、非private修饰,非final修饰,非构造方法等的实现过程 进行重新编写, **返回值和形参都不能改变。即外壳不变,核心重写!**重写的好处在于子类可以根据需要,定义特定 于自己的行为。 也就是说子类能够根据需要实现父类的方法。

方法重写的规则

  1. 子类在重写父类的方法时,一般必须与父类方法原型一致: 返回值类型 方法名 (参数列表) 要完全一致
  2. 被重写的方法返回值类型可以不同,但是必须是具有父子关系的
  3. 访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类方法被public修饰,则子类中重写该方 法就不能声明为 protected
  4. 父类被static、private修饰的方法、构造方法都不能被重写
  5. 重写的方法, 可以使用@Override 注解来显式指定。有了这个注解能帮我们进行一些合法性校验. 例如不小心将方法名字拼写错了 (比如写成 aet), 那么此时编译器就会发现父类中没有 aet 方法, 就会编译报错, 提示无法构成重写

重写和重载的区别

区别点重写(override)重载(override)
参数列表一定不能修改必须修改
返回类型一定不能修改【除非可以构成父子类关系】可以修改
访问限定符一定不能做更严格的限制(可以降低限制)可以修改

即:方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。

在这里插入图片描述

重写的设计原则

对于已经投入使用的类,尽量不要进行修改。最好的方式是:重新定义一个新的类,来重复利用其中共性的内容, 并且添加或者改动新的内容。

  • 静态绑定:也称为前期绑定(早绑定),即在编译时,根据用户所传递实参类型就确定了具体调用那个方法。典型代 表函数重载。

  • 动态绑定:也称为后期绑定(晚绑定),即在编译时,不能确定方法的行为,需要等到程序运行时,才能够确定具体 调用那个类的方法。

多态的具体体现

方法的多态

**重写和重载就体现多态 **

//方法重载体现多态
A a = new A();
//这里我们传入不同的参数,就会调用不同 sum 方法,就体现多态
System.out.println(a.sum(10, 20));
System.out.println(a.sum(10, 20, 30));

//方法重写体现多态
B b = new B();
a.say();
b.say();

对象的多态(核心,困难,重点)

  1. 一个对象的编译类型和运行类型可以不一致
  2. 编译类型在定义对象时,就确定了,不能改变
  3. 运行类型是可以变化的
  4. 编译类型看定义时 =号 的左边,运行类型看 =号的 右边
Animal animal = new Dog();//animal 编译类型是 Animal,运行类型 Dog
animal = new Cat();//animal 的运行类型变成了 Cat, 编译类型仍然是 Animal
public class PolyObject {
	public static void main(String[] args) {
		//体验对象多态特点
		//animal 编译类型就是 Animal , 运行类型 Dog
		Animal animal = new Dog();
		//因为运行时 , 执行到改行时,animal 运行类型是 Dog,所以 cry 就是 Dog 的 cry
		animal.cry(); //小狗汪汪叫
		//animal 编译类型 Animal,运行类型就是 Cat
		animal = new Cat();
		animal.cry(); //小猫喵喵叫
	}
}

多态注意事项

多态的前提:两个对象(类)存在继承关系

在这里插入图片描述

多态的向上转型

本质: 父类的引用指向了子类的对象(从小范围向大范围的转换)

语法:父类类型引用名 = new 子类类型();

特点:编译类型看左边,运行类型看右边

Animal animal = new Cat(); 

Object obj = new Cat();//可以吗? 可以,Object 也是 Cat 的父类
向上转型调用方法的规则:
  1. 可以调用父类中的所有成员(需遵守访问权限)

  2. 不能调用子类的特有的成员。因为在编译阶段,能调用哪些成员,是由编译类型来决定的

animal.catchMouse();//错误
  1. 最终运行效果看子类(运行类型)的具体实现, 即调用方法时,按照从子类(运行类型)开始查找方法 ,然后调用,与方法调用规则一致。

多态向下转型

语法:子类类型 引用名 =(子类类型)父类引用;

向下转型调用方法的规则:
  1. 只能强转父类的引用,不能强转父类的对象
  2. 要求父类的引用必须指向的是当前目标类型的对象
  3. 当向下转型后,可以调用子类类型中所有的成员

多态细节讨论

  • 属性没有重写之说!属性的值看编译类型
public class Test {
	public static void main(String[] args) {
		//属性没有重写之说!属性的值看编译类型
		Base base = new Sub();//向上转型
		System.out.println(base.count);// ? 看编译类型 10
		Sub sub = new Sub();
		System.out.println(sub.count);//? 20
	}
}

class Base { //父类
	int count = 10;//属性
}
class Sub extends Base {//子类
	int count = 20;//属性
}
  • instanceOf 比较操作符,用于判断对象的运行类型是否为 XX 类型或 XX 类型的子类型
public class Test {
	public static void main(String[] args) {
		BB bb = new BB();
		System.out.println(bb instanceof BB);// true
		System.out.println(bb instanceof AA);// true
        
		//aa 编译类型 AA, 运行类型是 BB
		//BB 是 AA 子类
		AA aa = new BB();
		System.out.println(aa instanceof AA);//true
		System.out.println(aa instanceof BB);//true
        
		Object obj = new Object();
		System.out.println(obj instanceof AA);//false
		String str = "hello";
		//System.out.println(str instanceof AA);
		System.out.println(str instanceof Object);//true
	}
}

class AA {} //父类
class BB extends AA {}//子类
  • 24
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值