在这一章中,我会讲解有关父类和子类的知识。

首先我们需要先了解一下父类和子类。

子类和父类

子类class和父类class之间有一定的关联,可以说子类是在父类的基础上创造的,比父类有更多的细节,但同时继承了父类的很多特性。父类所包含的方法都可以被子类实例化后的变量使用,但是父类实例化的变量无法使用在子类中但是父类没有的方法。

除此之外,子类class可以额外创建独属于子类的方法,而且也可以将父类class中的一些方法在子类class中重写。

另外,一个父类class可以有许多的子类class,但是每个子类class都只有一个父类class。

举个例子,如果我们需要记录关于某个学校里老师和学生的信息,我们就可以利用父类class和子类class来完成。

首先,既然父类class是子类class的基础,这也代表同一个父类的不同子类class都包括相同的父类特点。理解了这一点之后,我们要完成记录学生老师信息的任务,就可以从设置父类开始。学生和老师都需要的信息有姓名,性别,身高等等,因此我们可以将父类设置为person,并且将姓名,性别,身高作为全局变量写出来:

public class Person{
    private String name;
    private boolean isMale;
    private int age;
    public Person(String name,boolean isMale,int age){
        this.name=name;
        this.isMale=isMale;
        this.age=age;
    }
}

我们的父类就完成了,接下来可以开始写子类的框架了,子类的声明只需要在声明class后额外添加extends+父类class名称,格式大概是这样:

Public class classname extends superClassname{

}

先创建一个名为Teacher.java的文件,写出一个名为teacher的子类class来记录老师的信息,并且将老师的信息中需要的职位,薪水声明为全局变量:

public class Teacher extends Person{
    private double wages;
    private String position;
    public Teacher(String name, boolean isMale, int age,double wages,String position) {
        super(name, isMale, age);
        this.wages=wages;
        this.position=position;
    }
}

再在Student.java中写一个名为Student的子类,并且包括学号,gpa等全局变量:

public class Student extends Person{
    private int number;
    private double gpa;
    
    public Student(String name,boolean isMale,int age,int number,double gpa){
        super(name, isMale, age);
        this.number=number;
        this.gpa=gpa;
    }  
}

两者的框架结构大概相似。

由于子类也具有父类的特征,因此在写子类class的构造函数时,要用super关键字将父类构造函数所需的变量输入进去,这一步就相当于在子类class内创建了一个父类class,和我们平时用的实例化class的语句有些相似,如上文所示。

这样最基本的框架就完成了,添加方法的部分按普通class添加就可以了。但这种方法有一点很重要,那就是子类继承父类的这种特性。

继承(Inheritance)

这是子类方法的一大特点,即它直接使用父类的方法而不用在自己的class内部再写一次。我们沿用上文的例子,在父类(person)中写一个查看年龄的方法,为了方便后续举例,我在这里将返回值设置为String:

public class Person{
    private String name;
    private boolean isMale;
    private int age;
    public Person(String name,boolean isMale,int age){
        this.name=name;
        this.isMale=isMale;
        this.age=age;
    }
    public String getAge(){
        return String.valueOf(age);
    }
}

接下来我们在main方法中创建一个teacher的实例化,并且调用父类中的getAge()方法:

public static void main(String[] args) {
        Teacher t=new Teacher("white",true,30,3000.0,"teacher");
        System.out.println(t.getAge());
    }

会输出年龄:30

由此可以看出,父类中创建的方法,子类是直接可以使用的。但是在子类里创建的方法,父类object不能直接使用,我们可以联合方法重写来学习这个知识点。

方法重写(Method Overriding)

即在子类中重写父类已经创建的方法,就是在子类中写一个和父类里其中一个方法的名字,返回值,参数完全一样的方法,但是方法的内容会与父类略有不同

比如说,我们在子类里写一个getAge()方法,但是将返回值改为:The age of the teacher is +age,注意,由于子类方法中没有声明age这个变量,我们需要使用父类的getAge()来返回age的值,但是在编写class的过程中,我们需要用super.method()来调用父类的方法:

public class Teacher extends Person{
    private double wages;
    private String position;
    public Teacher(String name, boolean isMale, int age,double wages,String position) {
        super(name, isMale, age);
        this.wages=wages;
        this.position=position;
    }
    public String getAge(){
        return "The age of the teacher is "+super.getAge();
    }
}

 这时候我们再次运行

这时候再次运行t.getAge()方法,输出值就会改变:The age of the teacher is 30

但是此时我们创建一个person类型的对象:

并且调用getAge()方法:

public static void main(String[] args) {
        Teacher t=new Teacher("white",true,30,3000.0,"teacher");
        System.out.println(t.getAge());
        Person p=new Person("Per",false,20);
        System.out.println(p.getAge());
    }

会发现p.getAge()的返回值还是20,因此,子类可以使用或者重写父类的方法,但是父类不可以使用子类的方法。与之相似,子类可以包含一些父类中没有的方法,这些方法父类object也不可以使用。

比如说我们在teacher中创建一个返回工资的方法:

public class Teacher extends Person{
    private double wages;
    private String position;
    public Teacher(String name, boolean isMale, int age,double wages,String position) {
        super(name, isMale, age);
        this.wages=wages;
        this.position=position;
    }
    public String getAge(){
        return "The age of the teacher is "+super.getAge();
    }
    public double getWages(){
        return wages;
    }
}

这时候父类的p是无法使用这个方法的。

可能大家会觉得是因为父类中没有wages这个变量,但是通过上面的例子大家也发现了,在子类重写过父类的getAge()方法后,父类对象使用该方法时返回值还是没有改变,因此无论父类有没有wags,子类中写出的方法都不能被父类使用。

但是通过实例化,可以让一个object既能使用子类方法,又可以使用父类方法,我们之需要在实例化的时候在前半部分写父类class名称,后面参数用子类class就可以了:

public static void main(String[] args) {
        Teacher t=new Teacher("white",true,30,3000.0,"teacher");
        System.out.println(t.getAge());
        Person p=new Person("per",false,30);
        System.out.println(p.getAge());
        Person pt=new Teacher("w",false,35,3000.0,"teacher");
        System.out.println(pt.getWages());
}

这时候使用pt.getWages(),会返回工资:3000.0。

而这种object还有一个很大的特点,就是在遇到重写过的方法时,会优先使用子类重写的方法,比如说我们输入pt.getAge():

public static void main(String[] args) {
        Teacher t=new Teacher("white",true,30,3000.0,"teacher");
        System.out.println(t.getAge());
        Person p=new Person("per",false,30);
        System.out.println(p.getAge());
        Person pt=new Teacher("w",false,35,3000.0,"teacher");
        System.out.println(pt.getWages());
        System.out.println(pt.getAge());

}

会输出:The age of the teacher is 35

值得一提的是,可以使用:父类 object名=子类(参数);来实例化,但是,子类 object名=父类(参数);是错误的❌,会报错。

与此同时,同一个父类的子类就像两个独立的class,它们是无法互通的。比如说我们创建一个student 的object,并且使用getAge():

public static void main(String[] args) {
        Teacher t=new Teacher("white",true,30,3000.0,"teacher");
        System.out.println(t.getAge());
        Person p=new Person("per",false,30);
        System.out.println(p.getAge());
        Person pt=new Teacher("w",false,35,3000.0,"teacher");
        System.out.println(pt.getWages());
        System.out.println(pt.getAge());
        Student s=new Student("s",true,17,2,3.94);
        System.out.println(s.getAge());
}

会输出17,使用的是父类没经过重写的方法。

以上就是所有关于父类子类class以及继承,方法重写的知识了,希望这篇文章可以帮助大家哥哥好地掌握这部分内容。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐