类的继承

面向对象程序设计语言,具有的特性:继承性、封装性、多态性。

在Java语言中,继承的基本思想,就是从已有的类,派生出新的类来。

不同的类可能会有一些共同的特征和行为,可以将这些共同的特征和行为统一放在一个类中,使它们可以被其他类所共享。

1. 类继承的实现

格式:

[public] class SubClass extends SuperClass{
    
}

class 父类{}
class 子类 extends 父类{}

例1:设计一个“人”的类;

class Person{
    public String name;
    public int age;
    public Person(){
        
    }
    public Person(String name,int age){
        this.name = name ;
        this.age = age ;
        
    }
    public void speak(){
        System.out.println("my name is " + name);
    }
}
Person per = new Person();

例2:定义一个“员工”类,使得“员工类”具有人的所有特征和行为。另外还有自己的特征:员工工资,计算工资的操作等。

class Employee extends Person{
    public double salary;
    //public Employee();
    public Employee(double salary){
        this.salary = salary;
    }
    public Employee(String name,int age,double salary){
        super(name,age);
        this.salary = salary;
    }
    public double computeSalary(int hours,double rate){
        double salary = hours * rate ;
        return this.salary + salary ;
        
    }
}

类继承的说明:

(1) 子类继承父类中非private的成员变量和成员方法。protected

(2) 定义类时若缺省extends关键字,则定义的类为java.lang.Object类的直接子类。所有的类都是Object的子类。

(3) Java仅支持单重继承,一个类至多只有一个直接父类(超类)。若实现多重继承,可通过接口实现。

例3. 验证子类Employee及其对象使用相应的方法。

public class EmployeeTest{
    public static void main(String[] args){
        Employee emp = new Employee("小明",30,5000);
        System.out.println("姓名 = " + emp.name);
        System.out.println("年龄 = " + emp.age);
        emp.speak();
        System.out.println(emp.computeSalary(10,50.0));
    }
}

注意:父类中定义的private成员变量和方法不能被子类继承,因此在子类中不能直接使用。如果父类中定义了公共的访问方法和修改方法(getter() setter()),子类可以通过这些方法来访问或修改它们。

2. 方法覆盖

在子类中可以定义与父类中的名字、参数列表、返回值类型都相同的方法,这时子类的方法就叫做覆盖(overriding)或重写了父类的方法。

例4. 在Employee类中定义与其父类Person相同的speak()方法,用它来输出员工信息。

public void speak(){
    System.out.println("Hello, I am "+ name );
    System.out.println(" I am " + age );
    System.out.println("My salary is " + salary );
}

此方法便是对Person类中speak()方法的覆盖,如果子类覆盖了父类的方法,在调用相同的方法时,调用的是子类的方法。

为了避免在覆盖方法时写错方法头,可以使用@Override注解语法,即在要覆盖的方法前面添加@Override。

例5. Object类中有一个toString()的方法,在Employee类中覆盖其方法。

@Override
public String toString(){
    return "姓名:"  + name + "年龄:" + age ;
}

注意:@Override注解表示其后的方法必须是覆盖父类的一个方法。如果具有该注解的方法没有覆盖父类的方法,则编译器将会报告一个错误。

关于方法覆盖,有两点需要注意:

(1) private方法 不能覆盖。如果在子类中定义了一个方法在父类中是private的,则这两个方法无关。

(2) 父类中的static方法可以被继承,但不能被覆盖。如果子类中定义了与父类中的static方法完全一样的方法,那么父类中的方法被隐藏。父类中被隐藏的static方法仍然可以用“类名.方法名()”形式调用。

关于方法的重载与方法的覆盖的不同:

方法重载是在一个类中定义了多个名称相同,但是参数列表不同的方法。

方法覆盖是在子类中 为父类中的同名方法提供一个不同的实现。

要在子类中定义一个覆盖的方法,方法的参数列表及返回值都必须和父类的方法相同。

super关键字

在子类中可以使用super关键字,用来引用当前对象父类对象,一般用在三种情况:

(1)在子类中调用父类中被覆盖的方法,格式:

super.methodName()

(2) 在子类中调用父类的构造方法,格式:

super()

(3)在子类中访问父类中被隐藏的成员变量,格式:

super.variableName

4.调用父类的构造方法

子类不能继承父类的构造方法

super(paramlist)===>父类

super.super()===>爷爷类 不合法

在子类构造方法中,若没有使用super调用父类的构造方法,则编译器将在子类的构造方法的第一句自动加上super(),调用的父类的无参数的构造方法。