类的继承


概述

类的继承是指在一个现有类的基础上构建一个新类。

  • 新类称作子类,现有类称作父类。
  • 子类自动拥有父类所有可继承的属性和方法。

如何实现类的继承?

声明一个类继承另一个类,需要使用关键字extends。

比如我先创建一个Person类,代码如下:

public class Person {
    private char gender;

    public Person(){
        System.out.println("Person类无参构造方法执行");
    }

    public char getGender(){
        return gender;
    }

    public void setGender(char gender){
        this.gender = gender;
    }

    public void sleep(){
        System.out.println("要睡觉...");
    }

}

创建一个Student类,继承Person类,代码如下:

public class Student extends Person{
    private String name;
    int age;
    public Student(){}

    public Student(String name){
        this.name = name;
    }

    public String getName(){
        return name;
    }

    public void setName(String name){
        this.name = name;
    }

    public void intro(){
        System.out.println("我的性别是"+getGender());
    }

}

创建Student对象,程序入口代码如下:

    public static void main(String[] args) {
        Student stu1 = new Student("大西瓜");
        stu1.age = 10;
        stu1.gender = '男';//报错,private修饰的成员不可继承
        stu1.setGender('男');
        stu1.intro();
        stu1.sleep();
    }

运行结果如下:

Person类无参构造方法执行
我的性别是男
要睡觉...

可以看出,

  1. Student类通过extends关键字继承Person类后,虽然没有没有定义gender属性和sleep()方法,却能访问两个成员。
  2. private修饰的变量gender无法访问。

这就说明,子类继承父类时,自动拥有父类所有可继承的成员。而被private修饰的变量gender则属于不可继承的成员。

  1. 创建的是Student对象,为什么Person类的无参构造会被调用?

这就要从内存创建开始说起,创建Student对象,先开辟堆内存空间。不同以往,开辟的不是Student对象的空间,而是先开辟它的父类对象的空间

再创建子类对象Student,将父类的引用赋值给新增属性super

这就是为什么Person类构造方法被调用的原因了,

等于说是开辟了两块空间,一父一子两个对象,其中子类对象中的super属性指向父类,
我们在访问子类中不存在、父类中存在的成员时,就相当于是通过这个属性找到父类成员并访问的。

继承与权限修饰符的关系

下面通过这个表,为小伙伴们简单讲解继承的范围。

修饰符/访问范围 同一个类中 同一个包中 子类中 全局范围
public v v v v
protected v v v
default v v
private v

由上图,只有private修饰的类或类的成员不能被继承。

可能细心的小伙伴会发现,Person类中的age变量没有被修饰,修饰符应该属于default,结果却可以被子类访问

这是因为,

age的修饰符属于(default)默认修饰符,同一个包下可以访问,而Person类和student类就在同一个包下。

继承与类的关系

类的继承也有限制,请注意:

  1. Java中类仅支持单继承、不支持多继承,即一个类只有一个直接父类。
    class A{}
    class B{}
    class C extends A,B{}//不可同时继承多个类
  1. 多个类可以继承一个类
class A{}
class B extends A{}
class c extends A{}//B类和C类都可以继承A类
  1. 多层继承是允许的,即一个类的父类可以再去继承别的父类。
class A{}
class B extends A{}//B类继承A类,B类是A类的子类
class C extends B{}//C类继承B类,B类继承A类,C类也是A类的子类、C类可以访问B类和A类所有可继承的成员
  1. 子类可以重写父类的方法。
    子类中的重写方法和父类被重写的方法应具有相同的方法名、参数列表、返回值类型。

我们在Student类中添加父类的sleep()方法

    //与父类相同的方法名、参数列表、返回值类型。
    public void sleep(){
        System.out.println(name+"要睡觉...");
    }

程序入口,代码如下:

    public static void main(String[] args) {
        Student stu1 = new Student("大西瓜");
        stu1.sleep();
    }

结果如下:

Person类无参构造方法执行
大西瓜要睡觉...

此时发现,JVM调用的的是子类的sleep()方法而不是父类的,这就是方法的重写。

注意一点:子类重写父类方法时,不能使用比父类更严格的访问权限,

Person类中sleep()方法不变,子类Student中将修饰符改为比public权限更严格的private。

    private void sleep(){//报错,不能使用比父类更严格的访问权限
        System.out.println(name+"要睡觉...");
    }

但是如果父类的sleep()方法被private修饰,子类sleep()方法被比private权限更宽松的public修饰,则能够实现重写,顺利运行。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM