手把手教你学会Java中的面向对象之继承与多态(炼气篇)

手把手教你学会Java中的面向对象之继承与多态(炼气篇)

继承

继承的定义是啥

别急,家人们,我们先来想一个问题:

如果我们要定义一个狗类,是不是应该这样去写呀?

  1. 定义狗的名字
  2. 定义狗的年龄
  3. 定义狗的行为(吃)
public class Dog {
    public String name;//狗的名字
    public int age;  //狗的年龄

    //狗会做出的行为(动作)
    public void eat(){
        System.out.println("吃");
    }
}

如果我们要定义一个猫类,应该这样去写叭!

  1. 定义猫的的名字
  2. 定义猫的年龄
  3. 定义猫的行为(吃)
//定义一个猫类
class Cat{
    public String name;  //猫的名字
    public int age;  //猫的年龄

    //猫的行为(吃)
    public void eat(){
        System.out.println("吃");
    }
}

如果我们要定义一个鸡类,是不是也要这样去写呐?

  1. 定义鸡的名字
  2. 定义鸡的年龄
  3. 定义鸡的行为(吃)
//定义一个鸡类
class chicken{
    public String name; // 鸡的名字

    public int age;  //鸡的年龄

    //鸡的行为(吃)
    public void eat(){
        System.out.println("吃");
    }
}

此时此刻,聪明的你一定已经发现问题了,如果把所有的动物都写一个类,

那岂不是要累死,还好人类足够聪明(爱偷懒)

我们慢慢观察就可以发现其中的规律!

所谓的狗类,猫类,鸡类都有着共同的属性(名字和年龄)以及共同的行为(吃)

那这些类从本质上都属于动物类,所以我们只需要定义一个动物类(包括名字,年龄,吃)的类

然后让狗类,猫类,鸡类继承这个动物类就OK啦

  1. 定义一个动物类
  2. 定义动物的属性(名字,年龄)
  3. 定义动物的行为(吃)
//定义了一个父类,名叫动物的父类
public class Animal {
    
    public String name;   //定义动物的名字
    public int age;      //定义动物的年龄

    //定义动物的行为(吃)
    public void eat(){
        System.out.println("吃");
    } 
}

在这里插入图片描述

继承的目的

为了提高代码的复用性

小tips:

  1. 子类会继承父类的成员方法成员变量
  2. 子类不能继承父类的构造方法
  3. 子类也不能继承父类的static修饰的方法和属性(静态方法和静态属性属于类,不属于对象)

super关键字

super的作用:为了在子类方法中访问父类的成员

例子:

public class Dog extends Animal {
    public String name = "狗";//狗的名字
    public int age = 10;  //狗的年龄

    public Dog() {
    }
    //狗会做出的行为(动作)
    public void eat(){
        System.out.println(super.name); //会访问父类Animal的姓名
        super.eat();      //会访问父类eat的方法
        System.out.println("==========");
        System.out.println("狗吃");

    }
}
class Text{
    public static void main(String[] args) {
        //定义一个Dog对象
        Dog dog = new Dog();
        dog.eat();     //调用eat()方法
    }
}

在这里插入图片描述

小tips:

  1. super只能访问从父类继承过来的成员
  2. super只是一个关键字,不是父类对象的引用
  3. 作用是为了在子类的方法中访问父类的方法
  4. super在构造方法中不能与this()同时存在,都只能在第一行

super与this的区别

相同点:

  1. super与this都关键字
  2. 都只能在非静态方法中使用,来访问非静态成员
  3. 都只能是在构造方法中的第一条语句,不能同时存在

不同点:

  1. this表示当前对象的引用, super表示在子类方法中访问父类成员
  2. 在构造方法中this()表示在本类中调用其他的构造方法
  3. super()表示调用父类的构造方法
  4. 构造方法中一定有super(),(默认有), 而this(),我们不写则没有

如果一个类不想被继承,则使用final关键字来修饰

多态

多态定义

为了去完成一些行为,不同的对象会产生不同的状态,

即:父类引用指向了子类的对象

Animal dog = new Dog();

向上转型

定义:将子类对象赋值给父类引用
在这里插入图片描述

向上转型的两种方式:

1.直接赋值

Animal dog = new Dog();

2.方法传参和返回值

public class Text1 {
    public static void main(String[] args) {
       Cat cat = new Cat("小猫",23);
        fun2(cat);  //调用cat的eat()方法
        Animal animal = fun1();
        System.out.println(animal.name);  
    }

    //父类作为方法的返回值,可以接收任意子类
    public static Animal fun1(){
        Dog dog = new Dog("小狗",234);
        return dog;
    }

    //父类作为方法的参数,可以传输任意子类
    public static void fun2(Animal animal){
        animal.eat();
    }
}

在这里插入图片描述

向上转型的缺点

这个向上转型, 不能够去调用子类独有的,特有的方法

动态绑定

父类引用指向了子类型对象,并且调用了子类重写的方法

Animal animal = new Dog(); //父类型的引用animal指向了子类型的对象

animal.eat(); //调用了子类重写过后的eat()方法

例子:

//定义父类Animal
class Animal {
    public String name = "动物";   //定义动物的名字
    public int age = 10;      //定义动物的年龄

    //定义动物的行为(吃)
    public void eat(){
        System.out.println("动物吃");
    }

}


//子类狗继承父类Animal
class Dog extends Animal {
    public String name = "狗";//狗的名字
    public int age = 10;  //狗的年龄

    public Dog() {
    }

    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }

    //重写父类的同名的eat()方法
    public void eat(){
        System.out.println("狗吃");

    }
}


class Text2 {
    public static void main(String[] args) {
        Animal animal = new Dog();
        animal.eat();  //运行结果为子类的eat()狗吃
    }
}

在这里插入图片描述

静态绑定与动态绑定的区别

静态绑定(编译时绑定):

表示编译器在编译代码的时候就能够确定
调用的是父类的方法还是子类的方法(方法重载)

动态绑定(运行时绑定):

父类引用调用子类的重写方法,就叫做动态绑定

为什么?

Animal animal = new Dog();

animal.eat();

编译时看左边(Animal),运行时看右边(Dog)

编译器在编译过程中发现

这个eat()方法在编译过程中调用的是父类的Animal类,

但是在编译结束之后;
在运行过程中发现这个方法已经被子类重写了,于是就会去调用子类重写之后的方法
在这里插入图片描述

如何查看编译过程

1.第一步:在代码中鼠标右击,去找到该代码的目录,点击Show in Explorer
在这里插入图片描述
2.第二步:进入out文件夹,进入.class文件中,输入cmd
在这里插入图片描述
在这里插入图片描述
3.第三步:输入javap -c Text2(名字)
在这里插入图片描述
4.查看main方法
在这里插入图片描述
在这里插入图片描述

5.分析代码,在编译时,确实调用了Animal类的eat()方法

但是在运行时发现子类重写了eat()方法,

于是就调用了子类重写的eat()方法.

这个就是编译时看左,运行时看右.

重写

什么是重写

当父类的方法无法满足子类的要求是,就必须在子类重写这个方法

上面的例子中eat()方法就被重写了

重写的条件
  1. 重写的方法名必须和父类的方法相同
  2. 参数列表必须相同
  3. 返回值必须相同
重写与重载的区别
重写重载
方法名相同相同
参数列表相同不同
返回值相同(或具有继承关系)不影响(没所谓)
访问符相同(或只降不升,严格)不影响(没所谓)
重写的注意事项
  1. private的方法不能重写
  2. static的方法不能重写
  3. final的方法不能重写
  4. 构造方法不能重写
  5. 返回值可不同但必须有继承关系

向下转型

父类类型被强转为子类类型(非常不安全哦)

可以使用instanceof关键字来判断

总结

继承

  1. 目的是为了提高代码的复用性

  2. 使用过extends关键字来继承

  3. super的目的是为了在子类中访问父类成员

多态

多态核心: 是一种思想,父类引用指向子类对象,调用同名的重写方法来表现出不同的行为

多态发生的过程
  1. 第一步向上转型
  2. 第二步通过父类引用调用子类重写的方法
多态的作用
  1. 降低圆复杂度
  2. 增强代码的扩展度
多态的缺点
  1. 只有方法可以使用多态,属性不可
  2. 构造方法不能使用多态
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值