面向对象三大特性之一: 继承

继承是面向对象编程的重要特性,允许子类继承父类的属性和方法。在Java中,子类通过`extends`关键字实现继承。子类可以访问父类的成员变量和方法,但需提供自己的独特功能。`super`关键字用于在子类中调用父类的方法或成员。构造方法的调用顺序是先父类后子类,`final`关键字用于阻止进一步的继承或方法重写。

一:概念

继承(inheritance)机制:是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加新功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。继承主要解决的问题是:共性的抽取,实现代码复用。

下面我们来看一下什么是继承,例 :

public class Animal {
    public String name;

    public int age;

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

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

class Dog extends Animal {
    public void barks() {
        System.out.println(this.name + "汪汪汪");
    }
}
class Cat extends Animal {
    public void wag() {
        System.out.println(this.name + "喵喵喵");
    }
}

代码中的Animal属于父类,也称为基类、超类, cat和dog称为子类,也称为派生类

其中圈红的extends称为继承关键字。

继承的语法为:

修饰符 + class + 子类类名 + extends + 父类类名 {

//........

}

在子类当中肯定有父类的成员变量和成员方法,而父类不一定有子类的成员变量和成员方法。

    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.name = "小黄";
        dog.age = 1;
        Cat cat = new Cat();
        cat.name = "喵喵";
        cat.age = 1;
        System.out.println(dog.name + dog.age);
        System.out.println(cat.name + cat.age);
        dog.eat();
        cat.eat();
    }

这里可以看到我们的Dog类和Cat类里面没有定义name和age,但是依然可以访问,说明子类继承了父

类的成员变量和成员方法。

注意:

子类会将父类中的成员变量或者成员方法继承到子类中;

子类继承父类之后,必须要添加自己特有的新成员,体现出与父类的不同,否则就没有继承的必要了。

二:父类成员访问

  1. 子类中访问父类成员

①:子类成员变量名与父类成员变量名不同

public class Base {
    int a;
    int b;
}

class Derived extends Base {
    int c;

    public void Derived() {
        a = 10;
        b = 20;
        c = 30;
    }

    public static void main(String[] args) {
        Derived derived = new Derived();
        derived.Derived();
        System.out.println(derived.a + derived.b + derived.c);
    }
}

从上面代码可以看出不管是父类的成员变量还是子类的成员变量都赋值成功了,相加的和为60。

所以当父类成员变量名与子类成员变量名不同时,可以直接访问。

②:子类成员变量名与父类成员变量名相同

public class Base {
    int a;
    int b;
}

class Derived extends Base {
    int a;
    int b;
    int c;

    public void Derived() {
        a = 10;
        b = 20;
        c = 30;
    }

    public static void main(String[] args) {
        Derived derived = new Derived();
        Base base = new Base();
        derived.Derived();
        System.out.println(derived.a + derived.b + derived.c);
        System.out.println(base.a + base.b );
    }
}

这个我们可以看出当名字相同时,子类的赋值了,但是父类的还是默认值,说明采取就近原则。

注意:

  • 如果访问的成员变量子类中有,优先访问自己的成员变量。

  • 如果访问的成员变量子类中无,则向父类中找,如果父类中也没有,编译报错。

  • 如果访问的子类成员变量名与父类的成员变量名相同,则优先访问自己的。

2.子类访问父类成员方法

class Base extends Test02{
    public void d() {
        c();
        System.out.println("子类方法");

    }
    public void e() {
        c();
        d();
        //f();
    }
}

class Test02 {
    int a;
    int b;

    public void c() {
        System.out.println("父类方法");
    }
}

public class Test01 {

    public static void main(String[] args) {
        Base base = new Base();
        base.d();
    }
}

我们在子类方法中可以直接调用父类方法,但是父类中一定要有这个方法,没有的话编译器会报错。

这种是父类方法名与子类方法名不同,父类方法名与子类方法名相同时,优先访问子类。

那么我们要怎么才能访问父类呢??

三:super关键字

class Base extends Test02{
    public void d() {
        c();
        System.out.println("子类方法");
    }
    public void f() {
        d();
        super.d();
    }
    public void e() {
        c();
        d();
        //f();
    }
}

class Test02 {
    int a;
    int b;

    public void c() {
        System.out.println("父类方法");
    }
    public void d() {
        System.out.println("同名的父类方法");
    }
}

public class Test01 {

    public static void main(String[] args) {
        Base base = new Base();
        base.f();
    }
}

我们将代码改一下,调用了子类和父类的同名方法,可以看出super调用的那个同名的方法时父类的。

成员变量也是这样。

语法:

super.父类成员变量、super.父类成员方法

注意:

super与this相似,不能再静态方法中使用,因为super也是依赖对象的。

super是用来在子类方法中调用父类属性和行为的

四:子类构造方法

class A{
public int a;
    public int b;

    public A(int a, int b) {
this.a = a;
        this.b = b;
    }
}

class B extends A {
int c;

    public B(int a, int b, int c) {
super(a, b);
        this.c = c;
    }
public static void main(String[] args) {
        B b = new B(1,2,3);
    }
}

先有父后有子,调用构造方法也是,要先调用父类的构造方法,再调用子类的构造方法。

如果自定义了父类的构造方法,那么再子类中就要使用super来调用父类的构造方法,再初始化子类的属性。

那么就不能再再使用this(),因为super和this都必须再构造方法的第一行

五:super和this的相同点和不同点

  1. 相同点

this和super都是用来初始化成员属性的

this和super都不能在静态方法中使用,因为都是依赖对象的

  1. 不同点

this是对当前类中的属性和方法进行调用,super是对父类继承下来的方法和属性进行调用

再构造方法中,this()用于调用本类的构造方法,super调用父类的构造方法,并且不能同时出现再第一行

六:初始化

之前我们讲过初始化的顺序,分别是先初始化静态的,再初始化构造的,最后是构造方法。

那么再子类中呢??

class A{
    public int a;
    public int b;
    {
        System.out.println("父类构造块");
    }

    static {
        System.out.println("父类静态代码块");
    }
    public A(int a, int b) {
        this.a = a;
        this.b = b;
        System.out.println("父类构造方法");
    }
}

class B extends A {
    int c;

    {
        System.out.println("子类构造块");
    }

    static {
        System.out.println("子类静态代码块");
    }
    public B(int a, int b, int c) {
        super(a, b);
        this.c = c;
        System.out.println("子类构造方法");
    }
    public static void main(String[] args) {
        B b = new B(1,2,3);
        B c = new B(1,2,3);
    }
}

这里我们可以看出先执行静态代码块,还是先执行父类,然后子类的,静态代码块执行完再是父类的构造

块和构造方法,最后是子类的构造快和构造方法。

结论:

父类的代码块比子类的先执行

静态代码块只会执行一次

七:protected访问修饰限定符

在封装里面没讲这个,因为涉及到子类父类,就把他放到了继承中。

下面我们来认识一下protected的范围

可以看到只有在不同包的不同类中才会报错,无法访问。

注意:protected在不同包中的子类中要使用就得用super,但是super无法在static中使用,所以无法

在main函数中使用,要单独创建一个方法来使用。

八:继承方式

java中有单继承,多级继承、分层继承。

但是java中没有多继承,多继承需要用接口来是实现,后面会讲。

九:final关键字

final可以用来修饰成员变量和成员方法以及类。

final修饰成员变量表示该值只能被初始化一次。

修饰方法表示不能被重写。

修饰类表示不能被继承。

.

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值