Bootstrap

(5)继承与接口

上一章主要学习了类与对象的有关知识点,讨论了类的构成以及用类创建对象等内容,主要体现了面向对象编程的一个重要特点——数据的封装。

本章讲述这两方面的重要内容——类的继承与多态、接口的实现与多态。

1.子类与父类

继承是一种由已有的类创建新类的机制。

先编写一个有属性的一般类,再根据一般类编写具有特殊属性的新类,新类继承一般类的状态和行为。

由继承得到的类称为子类,被继承的类称为父类(超类)

Java不支持多重继承(子类只能有一个父类)

在类的声明中,通过关键字extends来声明一个类的子类,格式如下:

class 子类名 extends 父类名 {

...

}

2.子类的继承性

2.1子类和父类在同一个包中的继承性

若 子类和父类在同一个包中,那么,子类自然地继承了其父类中不是private的成员变量作为自己的成员变量,方法也是,继承的成员变量或方法的访问权限保持不变。

2.2子类和父类不在同一个包中的继承性

若 子类和父类不在同一个包中,子类不能继承父类友好变量和友好方法。子类能继承父类的protected和public成员变量和方法。

3.子类对象的构造过程

当用子类的构造方法创建一个子类的对象时,子类的构造方法总是先调用父类的某个构造方法。也就是说,如果子类的构造方法没有明显地指明使用父类的哪个构方法,子类就调用父类不带参数的构造方法。

4.成员变量的隐藏和方法重写

4.1成员变量的隐藏

子类也可以隐藏继承的成员变量,对于子类,可以从父类继承的成员变量,只要子类中声明的成员变量和父类中的成员变量同名,子类就隐藏了继承的成员变量。

注:子类对象可以调用从父类继承的方法操作隐藏的成员变量。

4.2方法的重写(方法覆盖)

子类通过重写(Override)可以隐藏已继承的实例方法。

1.重写的语法规则

        如果子类可以继承父类的某个实例方法,那么子类就有权重写这个方法。并且这个方法的名字、参数个数、参数类型和父类的方法完全相同。

2.重写的目的

        重写过后,可以把父类的状态和行为改变为自身的状态和行为。重写方法既可以操作继承的成员变量,也可以操作子类新声明的成员变量。

3.注意事项

        重写父类的方法时,不可以降低方法的访问权限。(可提高)

5.super关键字

子类可以隐藏从父类继承的成员变量和方法,如果在子类中想使用被子类隐藏的成员变量或方法,可以使用super关键字。

5.1使用super调用父类的构造对象

子类不继承父类的构造方法,因此,子类如果想使用父类的构造方法,必须在子类的构造方法中使用super来表示,并且super必须是子类的构造方法中的头一条语句。

  • 有参数的构造器:super(参数名称1,....,参数名称n);
  • 无参数的构造器(默认):super();

5.2使用super操作被隐藏的成员变量和方法

如果在子类中想使用被子类隐藏的成员变量或方法,可以使用关键字super,super.x,super.play()就是访问和调用被子类隐藏的成员变量x和方法play()。

6.final关键字

final关键字可以修饰类、成员变量和方法中的局部变量。

6.1 final类

可以使用final将类声明为final类,final类不能被继承,即不能有子类。

final class A{
...

}

6.2 final方法

如果用final修饰父类中一个方法,那么这个方法不允许子类重写。

6.3 常量

如果成员变量或局部变量被修饰为final,就是常量。常量在声明时没有默认值,所以在声明常量时必须指定该常量的值,而且不能发生变化。

7.对象的上转型对象

假设A类是B类的父类,当用子类创建一个对象,并把这个对象的引用放到父类的对象中,例如:

A a;

a = new B();

A a;

B b = new B();

a=b; 

这时,称对象a是对象b的上转型对象。

8.继承与多态

 多态性是指父类的某个方法被其子类重写时,可以各自产生自己的功能行为。不同的子类在重写父类的方法时可能产生不同的行为。

class 动物{
    void cry(){
    }
}

class 狗 extends 动物{
    void cry(){
        System.out.println("这是狗的叫声:汪汪...汪汪");
    }
}

class 猫 extends 动物{
    void cry(){
        System.out.println("这是猫的叫声:喵喵...喵喵");
    }
}

public class test{
    public static void main(String[] args){
        动物 animal = new 狗();  //animal是狗的上转型对象
        animal.cry();
        animal = new 猫();  animal是猫的上转型对象
        animal.crt();
    }
}

9.abstract类和方法

用关键字abstract修饰的类称为abstract类(抽象类)。例如:

abstract class A{

...

}

用关键字abstract修饰的方法称为abstract方法(抽象方法),对于abstract方法,只允许声明,不允许实现,而且不允许使用final和abstract同时修饰一个方法。例如:

abstract int min(int x,int y);

9.1 abstract类的特点与理解

9.1.1 abstract类的特点

        (1)abstract类中可以有abstract方法。

                abstract类中可以有abstract方法,也可以有非abstract方法。

                例如:

abstract class A
    abstract int min(int x,int y);
    int max(int x,int y){
        return x>y ? x:y;
    } 
}

        (2)abstract类不能用new运算符创建对象。

                如果一个非抽象类是某个抽象类的子类的子类,那么它必须重写父类的抽象方法,给出方法体。因此不允许使用final和abstract同时修饰一个方法。

        (3)abstract类的子类。

                如果一个非abstract类是abstract类的子类,它必须重写父类的abstract方法,即去掉abstract方法的abstract修饰,并给出方法体。如果一个abstract类是abstract类的子类,它可以重写父类的abstract方法,也可以继承父类的abstract方法。

        (4)abstract类的对象作上转型对象。

                可以使用abstract类声明对象,尽管不能使用new运算符创建该对象,但该对象可以成为其子对象的上转型对象,那么该对象就可以调用子类的重写方法。

9.1.2理解abstract类

        (1)抽象类封装了子类必须有的行为标准。

        只强调行为标准,即方法的名字、方法的类型,这就是抽象方法(没有方法体的方法)

        (2)体现子类根据抽象类里的行为标准给出的具体行为。

抽象类的重要特点,特别关心方法的名字、类型以及参数,但不关心这些操作具体实现的细节,即不关心方法体。

9.2 abstract类与多态

        在设计程序时,经常用到abstract类,原因是,abstract类只关心操作,不关心这些操作具体实现的细节。可以通过在abstract类中声明若干个abstract方法,表明这些方法在整个系统设计中的重要性,方法体的内容细节由它的非abstract子类去完成。

        使用多态进行程序设计的核心技术之一是使用上转型对象,,即将abstract类声明对象作为其子类的上转型对象,那么这个上转型对象就可以调用子类重写的方法。使用多态设计的好处,可以体现程序设计的所谓“开-闭”原则,对扩展开放,对修改关闭,增强代码的可维护性。

10.接口

        java不支持多继承性,即一个类不能有多个类(至多一个父类)。为了克服单继承的特点,Java使用了接口,一个类可以实现多个接口。

        使用关键字interface来定义一个接口。接口的定义和类的定义很相似,分为接口的声明和接口体。

10.1 接口的定义与使用

接口定义中含有一个接口声明(接口的名字)和接口体。

(1)接口声明

一般格式:interface 接口的名字 {  //接口声明

  //接口体

}

(2)接口体

接口体中包含static常量和方法定义两部分。

  1. 接口体中的抽象方法和常量:接口体中只有抽象方法,所有抽象方法的访问权限一定都是public(允许省略public、abstract修饰符)。接口体中所有static常量的访问权限一定都是public(允许省略public、、final和static修饰符,接口中不会有变量)。例如:
    interface Printable{
        public static final int Max = 100;  //等价写法:int Max = 100;
        public abstract void add();         //等价写法:void add();
        public abstract float sum(float x,float y);  //等价写法:float sum(float x,float y);
    }
  2. 接口体中的default实例方法: default实例方法的访问权限一定是public(允许省略public修饰符),注:不可省略default关键字
  3. 接口体中的static方法:允许在接口体中定义static方法,不可以用static和abstract同时修饰一个方法

(3)接口的使用

1)使用接口中的变量和static方法

        可以用接口名访问接口的常量、调用接口中的static方法,例如:

Printable.Max;

Printable.f();

2)类实现接口

一个类通过使用关键字implements声明自己实现一个或多个接口。若实现多个接口,用逗号隔开接口名,例如:
 

class A implements Printable,Addable{}

特别注意:

1.类实现某接口,但类不拥有接口的static方法。

2.接口中方法的访问权限都是public的,重写时不可省略public

实现接口的非abstract类一定要重写接口的abstract方法。---类实现了接口的方法

;