java继承和多态

继承和多态

继承

继承的概念

继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
生活中也有许多继承的例子,如图:
在这里插入图片描述

继承的基本语法

class 子类 extends  父类{
}

注意:

  1. 使用 extends 指定父类.
  2. Java 中一个子类只能继承一个父类 (而C++/Python等语言支持多继承).
  3. 子类会继承父类的所有 public 的字段和方法.
  4. 对于父类的 private 的字段和方法, 子类中是无法访问的.
  5. 子类的实例中, 也包含着父类的实例. 可以使用 super 关键字得到父类实例的引用

继承的好处

当我不使用继承时,代码如下:

class Animal {
    public String name;

    public Animal(String name) {
        this.name = name;
    }

    public void eat(String food) {
        System.out.println(this.name+"正在干饭,并表示"+food+"很不错");
    }
}
// Cat.java 
class Cat {
    public String name;

    public Cat(String name) {
        this.name = name;
    }
    public void eat(String food) {
        System.out.println(this.name+"正在干饭,并表示"+food+"很不错");
    }
}
// Bird.java 
class Bird {
    public String name;

    public Bird(String name) {
        this.name = name;
    }

    public void eat(String food) {
        System.out.println(this.name+"正在干饭,并表示"+food+"很不错");
    }

    public void fly() {
        System.out.println(this.name + "正在飞 ︿( ̄︶ ̄)︿");
    }
}

由上面代码可以发现,该代码存在大量的冗余代码,如:Animal类,Cat类,Bird类相比较可以发现该3个类都具备相同的eat方法,而且行为完全是 一样的,都有相同的属性name而且意义相同,这种代码维护性不高(维护性主要是后期需要修改的时候,就需要修改很多的代码,容易出错),所以要从根本上解决这代码的问题,就需要继承,以达到代码重用的效果。
使用继承后的代码:

class Animal {
    public String name;

    public Animal(String name) {
        this.name = name;
    }

    public void eat(String food) {
        System.out.println(this.name+"正在干饭,并表示"+food+"很不错");
    }
}
// Cat.java
class Cat extends Animal{
    public Cat(String name) {
    // 使用 super 调用父类的构造方法.
        super(name);
    }
}
// Bird.java
class Bird extends Animal{
    public Bird(String name) {
        super(name);
    }
    public void fly() {
        System.out.println(this.name + "正在飞 ︿( ̄︶ ̄)︿");
    }
}

多态

什么是多态

多态是同一个行为具有多个不同表现形式或形态的能力。多态就是同一个接口,使用不同的实例而执行不同操作。

向上转型

通常来说,向上转型表示往父类的方向转
在之前代码的基础上,写一个例子

Bird bird = new Bird("圆圆"); 
Animal bird2 = bird; 
// 或者写成下面的方式
Animal bird2 = new Bird("圆圆");

此时 bird2 是一个父类 (Animal) 的引用, 指向一个子类 (Bird) 的实例. 这种写法称为 向上转型.

动态绑定

当子类和父类中出现同名方法的时候, 再去调用会对前面的代码稍加修改,如以下代码:

class Animal {
    public String name;

    public Animal(String name) {
        this.name = name;
    }

    public void eat(String food) {
        System.out.println("我是一只小动物");
        System.out.println(this.name+"正在干饭,并表示"+food+"很不错");
    }
}
// Cat.java
class Cat extends Animal{
    public Cat(String name) {
        super(name);
    }

    @Override
    public void eat(String food) {
        System.out.println("我是一只小猫");
        System.out.println(this.name+"正在干饭,并表示"+food+"很不错");
    }
}
// Bird.java
class Bird extends Animal{
    public Bird(String name) {
        super(name);
    }
    @Override
    public void eat(String food) {
        System.out.println("我是一只小鸟");
        System.out.println(this.name+"正在干饭,并表示"+food+"很不错");
    }

    public void fly() {
        System.out.println(this.name + "正在飞 ︿( ̄︶ ̄)︿");
    }
}
public class Main{
public static void main(String[] args){
		Animal animal1 = new Animal("圆圆");
        animal1.eat("谷子");
        System.out.println("====================");
        Animal animal2 = new Bird("扁扁");
        animal2.eat("谷子");
}
}


我们发现:
animal1 和 animal2 虽然都是 Animal 类型的引用, 但是 animal1 指向 Animal 类型的实例, animal2 指向Bird 类型的实例.
针对 animal1 和 animal2 分别调用 eat 方法, 发现 animal1.eat() 实际调用了父类的方法, 而animal2.eat() 实际调用了子类的方法.
因此, 在 Java 中, 调用某个类的方法, 究竟执行了哪段代码 (是父类方法的代码还是子类方法的代码) , 要看究竟这个引用指向的是父类对象还是子类对象. 这个过程是程序运行时决定的(而不是编译期), 因此称为动态绑定

向下转型

向上转型是子类对象转成父类对象, 向下转型就是父类对象转成子类对象. 相比于向上转型来说, 向下转型没那么常见,但是也有一定的用途.

class Animal {
    public String name;
    public Animal(String name) {
        this.name = name;
    }
    public void eat(String food) {
        System.out.println("我是一只小动物");
        System.out.println(this.name+"正在干饭,并表示"+food+"很不错");
    }
}
// Cat.java
class Cat extends Animal{
    public Cat(String name) {
        super(name);
    }
    @Override
    public void eat(String food) {
        System.out.println("我是一只小猫");
        System.out.println(this.name+"正在干饭,并表示"+food+"很不错");
    }
}
// Bird.java
class Bird extends Animal{
    public Bird(String name) {
        super(name);
    }
    @Override
    public void eat(String food) {
        System.out.println("我是一只小鸟");
        System.out.println(this.name+"正在干饭,并表示"+food+"很不错");
    }

    public void fly() {
        System.out.println(this.name + "正在飞 ︿( ̄︶ ̄)︿");
    }
}
public class Main {
    public static void main(String[] args) {
        Animal animal2 = new Bird("扁扁");
        animal2.fly();
    }
}

在这里插入图片描述
注意:
编译过程中, animal 的类型是 Animal, 此时编译器只知道这个类中有一个 eat 方法, 没有 fly 方法.
虽然 animal 实际引用的是一个 Bird 对象, 但是编译器是以 animal 的类型来查看有哪些方法的。如果需要引用fly方法则需要对它进行向下转型
操作如下

Bird bird = (Bird)animal2; 
bird.fly(); 

在这里插入图片描述

评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

文墨轩

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

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

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

打赏作者

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

抵扣说明:

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

余额充值