1.多态的概念
简单来说,就是多种形态,具体点就是去完成某个行为,不同的对象去完成会有不同的形态。
举个例子:对于动物,他们吃的都是食物,但狗吃的是狗粮,猫吃的是猫粮,去完成吃这个行为,不同的对象会产生不同的形态。
2.多态实现条件
实现多态,必须满足下面几个条件,缺一不可:
1.必须在继续体系下
2.子类必须要对子类中的方法重写
3.通过父类的引用调用重写方法
多态体现:在代码运行时,当传递不同类的对象时,调用对应类中的方法
2.1向上转型
我们把子类的对象给父类,这种就叫做向上转型
格式:父类类型 对象名 =new 子类类型()
[Animal animal = new Cat("小黄",2);]
向上转型的优点:让代码实现更简单灵活。
向上转型的缺陷:不能调用到子类特有的方法
向上转型可能发生的几种情况
1. 直接赋值 2. 方法传参 3. 方法返回
我们来看个例子:依旧是猫和狗。在这个代码中,我们把子类的对象给父类,这就实现了向上转型,但要注意的是,虽然把子类的对象给了父类,但是在调用方法是,只能调用父类中的方法。
那如果我们想要给父类中的成员变量赋值,那么就需要在子类和父类中加构造方法去调用super语句,为其赋值。
package com.bai.demo2;
class Animal1{
public String name;
public int age;
public Animal1(String name,int age){
this.name=name;
this.age=age;
}
public void sleep(){
System.out.println(this.name+"正在睡觉");
}
}
class Dog1 extends Animal1{
public Dog1(String name,int age){
super(name,age);
}
public void eat(){
System.out.println(this.name+"吃东西");
}
}
class Cat1 extends Animal1{
public Cat1(String name,int age){
super(name,age);
}
public void bark(){
System.out.println(this.name+"正在叫");
}
}
public class demot {
public static void main(String[] args) {
Animal1 animal=new Dog1("小黄",2);
animal.sleep();
// animal.bark();//因为animal中并无bark方法,所以不能访问,编译器报错
}
}
结果:小黄正在睡觉
2.2方法的重写
重写也叫覆盖,重写是子类对父类非静态、非private修饰、非final修饰,非构造方法等的实现过程进行重新编写,返回值和形参都不能变(即外壳不变,核心重写)
重写的好处就是在于子类可以根据自己的需要,定义特定于自己的行为,也就是子类能过根据需要实现父类的方法。
重写的规则:
1. 被重写的方法返回值可以不同,但必须是具有父子关系的
2.子类在重写父类的方法时,一般必须与父类方法原型一致: 返回值类型 方法名 (参数列表) 要完全一致
3.访问权限不能比父类中被重写的方法的访问权限更低
4.父类被static,private修饰的方法、构造方法都不能被重写
在重写的时候,可以加上@Override来注释来显式指定。有这个注释,能帮我们进行一些合法性的检验。
例子:
class Animal1{
public String name;
public int age;
public Animal1(String name,int age){
this.name=name;
this.age=age;
}
public void eat(){
System.out.println(this.name+"正在吃东西");
}
}
class Dog1 extends Animal1{
public Dog1(String name,int age){
super(name,age);
}
public void eat(){
System.out.println(this.name+"吃狗粮");
}
}
class Cat1 extends Animal1{
public Cat1(String name,int age){
super(name,age);
}
public void eat(){
System.out.println(this.name+"吃猫粮");
}
}
public class demot {
public static void main(String[] args) {
Animal1 animal=new Dog1("小黄",2);
animal.eat();
}
}
结果:小黄吃狗粮
我们可以看到,我们虽然调用的是父类的eat,但实际输出的是子类的方法,这就是动态绑定
动态绑定发生的条件:1.发生向上转型 2.方法重写
静态绑定:在编译的时候就已经知道要执行哪个方法了
2.3重写(override)和重载(overload)的区别
即:方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。
下面是方法重载的例子
方法的重写在上面猫和狗动态绑定就是
2.4向下转型
将一个子类对象经过向上转型之后当成父类方法使用,再无法调用子类的方法,但有时候可能需要调用子类特有的 方法,此时:将父类引用再还原为子类对象即可,即向下转换
例子:
class Animal2{
public String name;
public int age;
public Animal2(String name,int age){
this.name=name;
this.age=age;
}
public void eat(){
System.out.println(this.name+"正在吃东西");
}
public void sleep(){
System.out.println(this.name+"正在睡觉");
}
}
class Dog2 extends Animal2{
public Dog2(String name,int age){
super(name,age);
}
public void eat(){
System.out.println(this.name+"吃狗粮");
}
}
class Cat2 extends Animal2{
public Cat2(String name,int age){
super(name,age);
}
public void bark(){
System.out.println(this.name+"正在叫");
}
public void eat(){
System.out.println(this.name+"吃猫粮");
}
}
public class test3 {
public static void main(String[] args) {
Animal2 a1=new Dog2("动物",1);
Cat2 c2=(Cat2)a1;
c2.bark();
}
}
上面的代码,向下转型后会出现类型异常,a1和2的类型不同,所以会异常 。
向下转型用的比较少,而且不安全,万一转换失败,运行时就会抛异常。Java中为了提高向
目录
1.多态的概念
2.多态实现条件
2.1向上转型
2.2方法的重写
2.3重写(override)和重载(overload)的区别
2.4向下转型
2.5使用多态的好处
下转型的安全性,引入 了instanceof,如果该表达式为true,则可以安全转换。
class Animal2{
public String name;
public int age;
public Animal2(String name,int age){
this.name=name;
this.age=age;
}
public void eat(){
System.out.println(this.name+"正在吃东西");
}
public void sleep(){
System.out.println(this.name+"正在睡觉");
}
}
class Dog2 extends Animal2{
public Dog2(String name,int age){
super(name,age);
}
public void eat(){
System.out.println(this.name+"吃狗粮");
}
}
class Cat2 extends Animal2{
public Cat2(String name,int age){
super(name,age);
}
public void bark(){
System.out.println(this.name+"正在叫");
}
public void eat(){
System.out.println(this.name+"吃猫粮");
}
}
public class test3 {
public static void main(String[] args) {
Animal2 a1=new Dog2("欧狗",1);
if(a1 instanceof Cat2){
Cat2 c2=(Cat2)a1;
c2.bark();
}
System.out.println("=========");
Animal2 a2=new Cat2("欧猫",1);
if(a2 instanceof Cat2){
Cat2 c3=(Cat2)a2;
c3.bark();
}
}
}
2.5使用多态的好处
1. 能够降低代码的 "圈复杂度", 避免使用大量的 if - else
2. 可扩展能力更强 如果要新增一种新的形状, 使用多态的方式代码改动成本也比较低.
多态缺陷:代码的运行效率降低。
1. 属性没有多态性 当父类和子类都有同名属性的时候,通过父类引用,只能引用父类自己的成员属性
2. 构造方法没有多态性
面型对象重的三个特性先到这。