Java基础 - 类的继承

面向对象是Java语言的核心,在Java中所有的类都继承于 java.lang.Object。当一个类没有显式使用继承的两个关键字(extends, implements),则默认继承 Object类。面向对象是现代软件设计模式的基础。合理利用它,不仅可以增强代码的可扩展性和复用性,同时也提高开发效率和降低维护成本。关于面向对象的详细介绍,请参考我的另一篇文章“面向对象编程详解”。

这篇文章主要介绍Java的面向对象编程特性。

继承

继承就是子类继承父类的特征和行为,使得子类具有父类相同的行为和数据结构。

语法格式

类的继承:extends关键字

// 顶层交通工具父类
public class Vehicle {

}

// Car使用extends关键字继承了Vehicle
// 轿车是交通工具的子类
public class Car extends Vehicle {

}

实现接口:implements关键字

// 可载人接口,所有的客车要可以实现这个接口来具备可载人的行为
public interface PeopleCarrier {
    
}

// 公共汽车实现了可载人接口
public class Bus implements PeopleCarrier{
    
}

特性

  • 仅支持单继承,即一个类只能继承一个类;但是可以实现多个接口,或接口与类混合的继承模式。例如:
// Car继承了Vehicle父类,同时又实现了3个接口,代表轿车具有载人、交税和陆地驾驶的行为
public class Car extends Vehicle implements PeopleCarrier, Taxable, DirveOnRoad {

}
  • 子类拥有父类的非私有(用private修饰的)成员变量和方法;子类可以添加自己的成员变量和方法,来扩展父类的行为特征:
public class Vehicle {
    
    // 所有Vehicle共有的方法
    public void dirve() {
        System.out.println("Let's have a ride!");
    }
    
}

public class Car extends Vehicle implements PeopleCarrier, Taxable, DirveOnRoad {

    // Car自己的方法
    public void changeGear() {

        System.out.println("Let's change gear");

    }

}

public class UseVehicle {

    public void dirveVehicle() {

        // Car对象具有父类Vehicle的drive()方法和Car的changeGear()方法
        Car car = new Car();
        car.dirve();
        car.changeGear();

    }

}
  • 子类可以重写父类的方法,详见本文“方法重写”部分
  • 支持多重继承,例如 B 类继承 A 类,C 类继承 B 类,所以按照关系就是 B 类是 C 类的父类,A 类是 B 类的父类。那么C同时具有B和A的行为,B具有A的行为:
// 继承了Car类
public class HybridCar extends Car{

    public void chargePower() {
        
    }
    
}

public class UseVehicle {

    public void dirveVehicle() {

        // HybridCar的对象具有父类Vehicle,Car的行为,同时也有自己的方法
        HybridCar hybridCar = new HybridCar();
        hybridCar.dirve();
        hybridCar.changeGear();
        hybridCar.chargePower();

    }

}

super和this

通过super关键字来访问父类成员,用来引用当前对象的父类实例;this是对自己的引用;

public class Vehicle {

    public void dirve() {
        System.out.println("Drive");
    }

}

public class Truck extends Vehicle {

    public void drive() {
        System.out.println("Drive truck");
    }

    public void driveBoth() {

        this.drive();
        super.dirve();

    }

}

public class UseVehicle {

    public void dirveVehicle() {

        Truck truck = new Truck();
        truck.driveBoth();

    }

}

// 输出结果为:
Drive truck
Drive

在子类没有覆盖父类方法的情况下,super和this关键字通常是会省掉的。这样调用者就会自动引用子类或父类的方法。例如,上面的例子,如果把Truck的dirve()改名为driveTruck(),driveBoth()方法就可以完全省掉super和this关键字:

public class Truck extends Vehicle {

    // 改名为driveTruck
    public void driveTruck() {
        System.out.println("Drive truck");
    }

    // 调用者就可以省掉super和this
    public void driveBoth() {

        driveTruck();
        dirve();

    }

}

final关键字

final关键字的语义是 "最终的",可以用来修饰变量(包括类属性、实例属性、局部变量和形参)、方法(包括类方法和实例方法)和类。

使用 final 关键字声明类,就是把类定义定义为最终类,不能被继承;如果用于修饰方法,该方法不能被子类重写:

public class Vehicle {
    
    public final void calculateTax() {
        
    }

}

public class Car extends Vehicle {

    // 编译报错,无法重写final修饰的父类方法
    public void calculateTax() {

    }

}

构造函数

子类必须调用父类的构造函数,但不是继承父类的构造函数,而是通过隐式或显式调用父类构造函数来满足继承关系。子类调用父类构造函数的规则是:

如果父类有默认构造函数(无参数),子类可以不显式调用;Java会自动调用父类的默认构造函数;

如果父类定了有参数构造函数(未使用默认构造函数),子类必须在构造函数中显式调用父类构造函数;

如果父类既定义了无参和有参构造函数,子类可以选择不调用父类构造函数,Java自动调用无参构造函数;子类也可以显式调用有参构造函数;

public class Vehicle {

    private String model;

    Vehicle() {

    }

    Vehicle(String model) {
        this.model = model;
    }
    
}

// 显式调用有参构造函数
public class Truck extends Vehicle {

    Truck() {
        super("GSL-6");
    }

}

// 隐式调用无参构造函数,也可以显式调用
public class Bus extends Vehicle {

    Bus() {
        
    }

    Bus(String model) {
        super(model);
    }

}

方法重写

子类可以重写父类的方法,改变父类的行为。子类根据自己的需要重新实现父类提供的方法,满足更具体的业务逻辑。利用方法重写可以实现灵活的对象间状态转化,即多态。

重写的方法必须与父类方法有一样的名字、形参和返回值类型。

public class Vehicle {

    void drive() {
        System.out.println("Can drive");
    }

}

public class Bus extends Vehicle {

    // 重写drive方法
    void drive() {
        System.out.println("Can drive bus");
    }

}

public class UseVehicle {

    public void dirveVehicle() {

        Vehicle vehicle = new Vehicle();
        vehicle.drive();

        Bus bus = new Bus();
        bus.drive();

    }

}

打印结果:
Can drive
Can drive bus

方法重写的规则如下:

  • 子类的方法与重写的方法形参必须完全一致;
  • 返回类型与被重写方法的返回类型可以不相同,但是必须是父类方法返回值的子类;
  • 访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为 public,那么在子类中重写该方法就不能声明为 protected;
  • 声明为 final 的方法不能被重写;声明为 static 的方法不能被重写,但是能够在子类中被再次声明;
  • 如果子类和父类在同一个包中,除了被private 和 final 方法,子类可以重写父类所有方法;
  • 如果子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法;

可以在子类的方法中用super()引用父类的被重写的方法。

以上就是对Java基础类的继承的相关介绍,希望老贾的这篇文章能帮到大家。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

做IT的小伟

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

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

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

打赏作者

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

抵扣说明:

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

余额充值