java继承和多态详解

前言

继承和多态刚开始是比较难理解的,要做到多看,多敲代码。
在这里插入图片描述

一、继承

有的时候客观事物之间就存在一些关联关系, 那么在表示成类和对象的时候也会存在一定的关联。
为了方便理解,我们先看下面一段代码。

(1)例如, 设计一个类表示动物

// Animal.java 
public 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 这几个类中存在一定的关联关系:
1)这三个类都具备一个相同的 eat 方法, 而且行为是完全一样的.
2)这三个类都具备一个相同的 name 属性, 而且意义是完全一样的.

(2)语法规则

class 子类 extends 父类 { 
} 

对于上面的代码, 可以使用继承进行改进. 此时我们让 Cat 和 Bird 继承自 Animal 类, 那么 Cat 在定义的时候就不必再写 name 字段和 eat 方法。

class Animal { 
    public String name; 
    public Animal(String name) { 
        this.name = name; 
    } 
    public void eat(String food) { 
        System.out.println(this.name + "正在吃" + food); 
    } 
} 
class Cat extends Animal { 
    public Cat(String name) { 
        // 使用 super 调用父类的构造方法.  
        super(name); 
    } 
} 
class Bird extends Animal { 
    public Bird(String name) { 
      super(name); 
    } 
    public void fly() { 
        System.out.println(this.name + "正在飞 ︿( ̄︶ ̄)︿"); 
    } 
} 
public class Test { 
    public static void main(String[] args) { 
        Cat cat = new Cat("小黑"); 
        cat.eat("猫粮"); 
        Bird bird = new Bird("圆圆"); 
        bird.fly(); 
    } 
} 

extends 英文原意指 “扩展”. 而我们所写的类的继承, 也可以理解成基于父类进行代码上的 “扩展”.
例如我们写的 Bird 类, 就是在 Animal 的基础上扩展出了fly方法.

(3)注意

如果我们把 name 改成 private, 那么此时子类就不能访问了

(4)字段和方法访问权限

private: 类内部能访问, 类外部不能访问
默认(也叫包访问权限): 类内部能访问, 同一个包中的类可以访问, 其他类不能访问.

protected: 类内部能访问, 子类和同一个包中的类可以访问, 其他类不能访问.

public : 类内部和类的调用者都能访问
在这里插入图片描述

二、多态

首先需要实现多态需要满足一些条件:
1) 继承关系上满足向上转型
2)子类和父类 有同名的覆盖/重写方法
3)通过父类对象的引用去调用这个重写的方法
完成以上三步就会发生动态绑定,动态绑定是多态的基础.

一、向上转型

(1)在刚才的例子中, 我们写了形如下面的代码

Bird bird = new Bird("圆圆"); 

这个代码也可以写成这个样子

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

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

(2)向上转型方法有三种

1)直接赋值

Animal animal = new Dog("圆圆",7);

2)方法的参数,传参是向上转型

public static void funcl(Animal animal){

}
public static void main(String[] args){
	Dog dog = new Dog("圆圆",6);
	func1(dog);
}

3)返回值向上转型


public static Animal func2(){
	Dog dog = new Dog("圆圆",19);
	return dog;
}

二、重写

针对刚才的 eat 方法来说:
子类实现父类的同名方法, 并且参数的类型和个数完全相同, 这种情况称为 覆写/重写/覆盖(Override).

(1)关于重写的注意事项

1)最基本的返回值 参数列表 方法名必须是一样的
2)被重写的方法的访问修饰限定符在子类中要大于等于父类的
3)被private修饰的方法不可以被重写的
4)被static修饰的方法是不可以被重写的
5)被final修饰的方法是不可以被重写的

三、动态绑定

子类和父类中出现同名方法的时候, 再去调用会出现什么情况呢?
对前面的代码稍加修改, 给 Bird 类也加上同名的 eat 方法, 并且在两个 eat 中分别加上不同的日志.

// Animal.java 
public class Animal { 
    protected String name; 
    public Animal(String name) { 
        this.name = name; 
    } 
    public void eat(String food) { 
        System.out.println("我是一只小动物"); 
        System.out.println(this.name + "正在吃" + food); 
    } 
} 
// Bird.java 
public class Bird extends Animal { 
    public Bird(String name) { 
        super(name); 
    } 
    public void eat(String food) { 
        System.out.println("我是一只小鸟"); 
        System.out.println(this.name + "正在吃" + food); 
    } 
} 
// Test.java 
public class Test { 
    public static void main(String[] args) { 
        Animal animal1 = new Animal("圆圆"); 
        animal1.eat("谷子"); 
        Animal animal2 = new Bird("扁扁"); 
        animal2.eat("谷子"); 
    } 
} 
// 执行结果 
我是一只小动物 
圆圆正在吃谷子 
我是一只小鸟 
扁扁正在吃谷子 

此时, 我们发现:
animal1 和 animal2 虽然都是
Animal 类型的引用, 但是 animal1 指向
Bird 类型的实例.
针对 animal1 和 animal2 分别调用 eat 方法, 发现
animal2.eat() 实际调用了子类的方法

四、多态的好处

类调用者对类的使用成本进一步降低.
封装是让类的调用者不需要知道类的实现细节.
多态能让类的调用者连这个类的类型是什么都不必知道, 只需要知道这个对象具有某个方法即可

  • 43
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小强在此

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

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

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

打赏作者

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

抵扣说明:

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

余额充值