面向对象程序之多态

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. 构造方法没有多态性

面型对象重的三个特性先到这。

  • 24
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhyhgx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值