Java宝典-继承和多态


封装,继承,多态是面向对象的三大特性,今天我们学习继承和多态~

1. 继承

继承: 继承指一个类(子类)可以继承另一个类(父类)的属性和者方法,子类也能在保持原有的特性的基础上进行拓展.继承是面向对象编程中使代码可以复用的一种方式,继承完成的工作是:共性的抽取和代码的复用.
举个例子: 猫猫和狗狗都是动物,猫猫有年龄,毛发颜色等属性,有吃饭,睡觉等行为;这些属性和行为狗狗也有,因此可以将这些共性抽取出来,实现代码复用,减少代码的冗余

1.1 继承语法

继承使用extends关键字,语法如下:

修饰符 class 子类 extends 父类 {
	//......
}

例:将姓名,年龄,毛发,吃饭,睡觉抽取成一个Animal类,让Dog和Cat继承Animal类(在继承父类的基础上,子类也有自己特有的行为和属性)
父类Animal:

class Animal {
    public String name;//年龄
    public int age;//年龄
    public String color;//毛发

    public void eat() {
        System.out.println(this.name + "正在吃饭");
    }

    public void sleep() {
        System.out.println(this.name + "正在睡觉");
    }
}

子类Dog

class Dog extends Animal {
    public void bark() {
        System.out.println(this.name + "正在汪汪叫");
    }
}

子类Cat

class Cat extends Animal {
    public void meow() {
        System.out.println(this.name + "正在喵喵叫");
    }
}

1.2 成员访问的规则

子类访问成员时,不管是成员变量还是成员方法,都遵循以下规则:

  1. 如果子类当中有,优先访问子类中的
  2. 如果子类中没有,再去访问父类中的
  3. 如果子类中没有,父类中也没有,则会报错
    例:
class A {
    int a = 10;
    int b = 20;
    public void Func() {
        System.out.println("AFunc");
    }
}

class B extends A {
    int a = 1;
    public void printNum() {
        System.out.println(a);
    }
    public void Func() {
        System.out.println("BFunc");
    }
}

public class Main {
    public static void main(String[] args) {
        B b = new B();
        b.printNum();
        b.Func();
    }
}

运行结果:
在这里插入图片描述
问题: 如果子类和父类中有重名的变量,但是我就是想要得到父类中的那个变量,该怎么办?
答: 使用super关键字

1.3 super关键字

使用super关键字可以实现在子类中访问父类成员

class A {
    int a = 10;
    int b = 20;
}

class B extends A {
    int a = 1;
    public void printNum() {
        System.out.println(super.a);
    }
}

public class Main {
    public static void main(String[] args) {
        B b = new B();
        b.printNum();
    }
}

此时输出的是父类中的a(10)
在这里插入图片描述
注意事项:
super只能在非静态的方法中使用

1.4 再谈构造方法

我们再复习一下构造方法的特点:

构造方法的名字与类名相同,没有返回值,可以构成重载,创建对象时由编译器调用,可以根据自己的需求提供参数不同的构造方法

先有父再有子,所以当发生继承时,实例化一个子类对象时,先要调用父类的构造方法,帮助父类的成员的初始化,再调用子类自己的构造方法,将子类新的成员初始化
注意事项:

  1. 如果父类中没有自定义构造方法,子类中第一行会有隐藏的super();这是编译器自动提供的,super()表示调用父类构造方法
  2. 子类的构造方法中,super()只能出现在第一行
  3. super()不能和this()同时出现

1.5 super和this的区别和联系

不说废话,直接上结论!!!

相同点:

  • this和super都不能在静态方法中使用
  • 如果在在构造方法中使用,都必须在第一行

不同点:

  • this是当前对象的引用,而super是从父类继承下来的那部分的引用
  • 非静态成员方法中使用时:this用来访问本类的方法和属性;super用来访问父类继承的方法和属性
  • 构造方法中使用时:this(…)用于调用本类中的其他构造方法(构成重载的);super(…)用于调用父类的构造方法
  • 发生继承时,子类构造方法中一定会存在super(…)的调用,不管用户是否手动添加构造方法,而this(…)
    如果用户不写则没有
    在这里插入图片描述

1.6 关于代码块的执行

在发生继承的情况下,实例化一个子类对象,代码执行顺序是怎么样的?看下面代码

class A {
    public A() {
        System.out.println("父类构造方法");
    }

    {
        System.out.println("父类实例代码块");
    }

    static {
        System.out.println("父类静态代码块");
    }

class B extends A {
    public B() {
        System.out.println("子类构造方法");
    }

    {
        System.out.println("子类实例代码块");
    }

    static {
        System.out.println("子类静态代码块");
    }

}

public class Main {
    public static void main(String[] args) {
        B b1 = new B();
        System.out.println("===========");
        B b2 =new B();
    }
}

运行结果:
在这里插入图片描述
结论:

  • 1.执行顺序:父类静态>>子类静态>>父类实例>>父类构造>>子类实例>>子类构造
  • 2.静态代码块只执行一次,实例代码块和构造方法中的代码每实例一个对象就执行一次
  • 3.父类总是比子类先执行

1.7 protected关键字

protected关键字修饰的成员,在不同包中的类也能使用,前提是发生继承
在这里插入图片描述

1.8 继承方式

在java中,继承方式有3种:

  1. 单继承:一个类继承另一个类
  2. 多层继承:A类被B继承,B类又被C继承
  3. 不同类继承同一个类
    java中不支持多继承(一个类继承多个类)
    在这里插入图片描述

1.9 final关键字

final关键字课用来修饰变量,方法,类作用如下:

  • final修饰变量:表示该变量是常量
  • final修饰方法:表示该方法不能被重写
  • final修饰类:表示该类不能被继承

2. 多态

多态:当完成同一种行为,不同对象会实现出不同的状态,这就是多态

2.1多态实现的条件

  • 发生多态的前提是发生了继承
  • 子类必须要对父类中的方法进行重写
  • 通过父类的引用来调用重写的方法

2.2 重写

重写(override),重写是指子类对父类的方法重新编写.重写可以根据需求实现父类的方法
方法重写的规则

  • 重写的方法,方法名,参数列表,返回值要和父类的完全一样
  • 被重写的方法的返回值可以不同,但是必须构成父子关系
  • 重写方法时,子类的方法访问权限必须大于等于父类(访问权限:public>protected>默认>private)
  • 被static,private,final修饰的方法不能被重写
  • 构造方法不能被重写
  • 使用@override注解,能帮助我们一些错误(比如方法名不同,会提提示报错)

重载和重写的区别:
在这里插入图片描述

2.3 向上转型和向下转型

2.3.1 向上转型

向上转型就是用父类引用来接收创建的子类对象

Father f1 = new Son();

向上转型可以通过1.直接赋值2.参数传递3.返回值传递三种方法实现
注意事项:

  • 不能调用子类特有的方法,如上述代码中f1不能调用Son类特有的方法

例:

class Animal {
}

class Dog extends Animal {
}

定义父类Animal和子类Dog,

public static void main(String[] args) {
		//向上转型:
        Animal animal1 = new Dog();
    }

2.3.2 向下转型

和向上转型相反,向下转型是用子类来接受创建的父类对象
例:

public static void main(String[] args) {
        Dog dog = new Dog();
        Animal animal = new Animal();
        dog = (Dog) animal;//此时需要将animal强制转换为Dog类型
    }

2.3.3 instanceof

向下转型使用较少,而且不安全,如果转换失败会抛出异常,为了提高安全性,java引入了instanceof,表达式如果为true表示安全转换
使用案例:

    public static void main(String[] args) {
        Animal animal = new Dog();
        Dog dog = new Dog();
        if (animal instanceof Dog) {
        //animal instanceof Dog表示:如果animal属于Dog类
            dog = (Dog) animal;
        }
    }

2.4 静态绑定和动态绑定

静态绑定: 也叫早绑定,在编译时,根据传递的参数就能确定调用了哪个方法.例如调用重载的方法时,根据参数的个数/类型就知道调用的是哪个重载的方法
动态绑定: 也叫晚绑定,动态绑定是在运行时才能确定调用了哪个方法

2.5 理解多态

看代码:

class Animal {
    public void eat() {
        System.out.println("吃饭");
    }
}

class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("吃狗粮");
    }
}

class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("吃猫粮");
    }
}

public class Main {
    public static void eat(Animal animal) {
        animal.eat();
    }

    public static void main(String[] args) {
        Dog dog = new Dog();
        Cat cat = new Cat();
        eat(dog);
        eat(cat);
    }
}

运行结果:
在这里插入图片描述
可以发现,调用同一个eat方法,Dog类型的对象调用和Cat类型的对象调用,输出的结果不同,这就是多态!!!你get到了吗?

2.6 多态的优点和缺点

多态的优点:

  1. 多态能够减少代码量
  2. 可扩展能力强

多态的缺点:

  1. 属性没有多态性:当父类和子类有同名的成员属性时,父类只能引用父类自己的
  2. 构造方法没有多态性
  3. 尽量不要在构造方法中调用重写的方法!!!
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值