类和对象之继承

一. 什么是继承

继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。

二. 继承的语法

关键字 extends 表明正在构造的新类派生于一个已存在的类。

public class Employee {
    private String name;
    private double salary;
    private Date hireDay;
    public Employee(String n, double s, int year, int month, int day)
    {
        name = n;
        salary = s;
        GregorianCalendar calendar = new GregorianCalendar(year, month, day);
        hireDay = calendar.getTime();
    }
    public String getName() {
        return name;
    }
    //more method
   ......
}

尽管 Employee 类是一个超类,但并不是因为它位于子类之上或者拥有比子类更多的功能。恰恰相反,子类比超类拥有的功能更加丰富。在 Manager 类中,增加了一个用于存储奖金信息的域,以及一个用于设置这个域的方法:

public class Manager extends Employee{//extends继承Employee类
    ...
    private double bonus;
    public void setBonus(double bonus) {
        this.bonus = bonus;
    }
}

然而,尽管在 Manager 类中没有显式地定义 getName 和 getHireDay 等方法,但属于 Manager 类的对象却可以使用它们,这是因为 Manager 类自动地继承了超类 Employee 中的这些方法。同样,从超类中还继承了 name、salary 和 hireDay 这 3 个域。这样一来,每个 Manager 类对象就包含了4个域:name、salary、hireDay 和 bonus。

在通过扩展超类定义子类的时候,仅需要指出子类与超类的不同之处。因此在设计类的时候,应该将通用的方法放到超类中,而将具
有特色用途的方法放在子类中,这种将通用的功能放到超类的做法,在面向对象程序设计中十分普遍。

然而,超类中的有些方法对子类 Manager 并不一定适用。例如,在 Manager 类中的 getSalary 方法应该返回薪水和奖金的总和。为此,需要提供一个新的方法来覆盖(override)超类中的这个方法:

@Override
public double getSalary() {
    return salary + bonus;//won't work
}

然而,这个方法并不能运行。这是因为 Manager 类的 getSalary 方法不能直接地访问超类的私有域。也就是说,尽管每个 Manager 对象都拥有一个名为 salary 的域,但在 Manager 类的 getSalary 方法中并不能够直接地访问 salary 域。只有 Employee 类的方法才能够访问私有部分。如果 Manager 类的方法一定要访问私有域,就必须借助共有的接口,Employee 类中的共有方法正式这样一个接口。

@Override
public double getSalary() {
    return super.getSalary() + bonus;
}
super 关键字有两个用途:一是调用超类的方法,二是调用超类的构造器。
super 不是一个对象的引用,不能将 super 赋给另一个对象变量,它只是一个指示编译器调用超类方法的特有关键字。

由于 Manager 类的构造器不能访问 Employee 类的私有域,所以必须利用 Employee 类的构造器对这部分私有域进行初始化,我们可以通过 super 实现对超类构造器的调用。使用 super 调用构造器的语句必须是子类构造器的第一条语句。

三. 继承初始化过程

public class Animal {
    public Animal() {
        System.out.println("--Animals--");
    }
    public static int printInit(String s) {
        System.out.println(s);
        return 30;
    }
}

public class Bird extends Animal {
    private static int B = Animal.printInit("static Bird region init");
    public Bird(){
        System.out.println("--Bird--");
    }
    }

public class Parrot extends Bird {
    public Parrot(){
        super();
        System.out.println("--Parrot--");
    }
    public static void main(String[] arg) {     
        Parrot parrot = new Parrot();
    }
}

运行结果:

--Animals--
--Bird--
--Parrot--

四. 继承的分类

纯继承关系是纯粹的“is-a”(是一种)关系,因为一个类的接口已经确定了它应该是什么。继承可以确保所有的导出类具有基类的接口,且绝对不会少。基类可以接收发送给导出类的任何消息,因为二者有着完全相同的接口。

五. 继承的特性

    * Java 语言的继承是单继承,不允许一个类继承多个父类。
    * java支持多层继承(继承体系)。
    * 子类和父类是一种相对概念。 
            *   备注:顶层父类是Object类,所有的类默认都继承Object类。   

1、继承后的特点---成员变量:

    1. 子类只能获取父类非私有成员
    2. 子父类的成员变量的名字不一样时,直接获取父类的成员变量
    3. 子父类中成员变量名字是一样的
                * 就近原则,谁离我近我就用谁
                * 如果有局部变量就使用局部变量
                * 如果没有局部变量,有子类的成员变量就使用子类的成员变量
                * 如果没有局部变量和子类的成员变量,有父类的成员变量就使用父类的成员变量
* 备注:父类中的成员变量是非私有的,子类才可以直接访问。若父类中的成员变量私有了,子类不能直接访问的。
               通常编码时,我们一般遵循封装的原则,可以在父类中提供公共的setXxx()和getXxx()方法。

例如:

public class ExtendsDemo2 {
    public static void main(String[] args) {
        Kid k = new Kid();
        k.show();
    }
}
class Dad{
    String name="大葱";
}
class Kid extends Dad{
    String name="二葱";
    public void show() {
        String name = "三葱";
        System.out.println(super.name);
        System.out.println(this.name);
        System.out.println(name);
    }
}

2:继承后的特点---成员方法:

    1. 子父类的成员方法的名字不一样时,直接获取父类的成员方法
    2. 子父类中成员方法名字是一样的
            * 成员方法重名---重写(Override)
            * 方法重写:子类出现于父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效应
                             也称为重写或者复写。声明不变,重新实现。
            *重写的应用
               子类可以根据需要,定义特定于自己的行为,即沿袭了父类的功能名称,又能根据子类的需要重新实现父类
               的方法,从而进行扩展增强。
            * 方法额重载:在一个类中,有多个重名的方法,但是其参数不一样
             (参数的个数,参数的类型,参数的顺序),和返回值无关
备注:
           1.子类方法重写覆盖父类方法时,必须保证权限大于等于父类的权限。
           2.子类方法重写父类方法时,返回值类型,方法名和参数列表必须一模一样。
                        在没有使用@Override时,子类定义父类方法时,方法名和参数列表可变,返回值类型不可变。

六:继承的优点

在面向对象语言中,继承是必不可少的、非常优秀的语言机制,它有如下优点:

  • 代码共享,减少创建类的工作量,每个子类都拥有父类的方法和属性;
  • 提高代码的重用性;
  • 子类可以形似父类,但又异于父类;
  • 提高代码的可扩展性,实现父类的方法就可以“为所欲为”了。
  • 提高产品或项目的开放性。

猜你喜欢

转载自blog.51cto.com/14954398/2545526