用于定义类与类之间关系的关键字
extends
1、作用:
- 类的继承:只允许单继承
- 接口的继承:允许多继承
- 泛型定义时的类型边界
- 泛型使用时通配符的边界
2、类的继承:
面向对象的三大特征:封装 — 通过访问限定符体现、继承、多态 。
- 继承的目的:代码的复用性,也就是懒得再写一遍甚至多遍重复的代码。
继承要表达的是一组有关系的类:子类是一种特殊的父类,表示的是父类的一个子集。例如:
class Animal {
void bark() {}
}
class Bird {}
class Cat {}
上述例子中,类 Bird 和类 Cat 均为特殊的类 Animal,且均为类 Animal 的子集。
- 语法:
在类的定义中体现。
class Animal {}
class Bird extends Animal {}
Animal:父类(parent 类)、基类(base 类)、超类(super 类)
Bird:子类(child 类)、派生类(derivative 类)
子类允许访问父类中除了被 private 修饰的属性和方法。
Object 是所有类的一个祖先类。
3、方法的覆写和重载:
发生在继承和接口中。
- 方法的覆写(Override):
子类重写了父类的方法:
- 发生在子类上,必须实现和父类方法名称相同、形参列表相同、返回类型相同的方法。允许返回值类型是父类方法返回类型的子类,例如:List method(); 和 ArrayList method();
- 子类的访问限定符不能比父类的更封闭(更严格)。
- 目的:针对同一行为,表现出和父类不同的方式。
- 一般建议使用 @Override 注解进行注释。
- 方法的重载(Overload):
即:方法名称相同,形参列表不同。
方法的签名 = 方法名称 + 形参列表
4、对象模型:
可以认为:在子类的对象中,存在一个完全体的父类对象。弗雷德所有属性在子类对象中都是存在的,但可能会没有访问权限。
访问限定:子类能否访问父类的属性和方法。
- public、protected 可以
- default 在同一个包内可以
- private 不可以
5、名字遮挡问题:
class A {
int a;
}
class B extends A {
int a;
public void method(int a) {}
}
变量名 | 是否歧义 | 解释 |
a | 是 | 1. 局部变量、形参 a;2. 本类或父类中的属性 a;3. 外部类中的 a。 |
this.a | 是 | 本类或父类中的属性 a。 |
super.a | 否 | 父类的属性 a。 |
Outter.this.a | 否 | 外部类的属性 a。 |
6、继承 VS 组合:
此处和语法无关,主要指设计角度。
class 遥控器 {
void volumeUp();
void volumeDown();
}
class 电视 {
遥控器 x;
void volumeUp() {
x.volumeUp();
}
}
7、接口的多继承:
一个接口能继承另一个接口,和类之间的继承方式比较相似。接口的继承使用 extends 关键字,子接口继承父接口的方法。
在 Java 中,类的多继承是不合法的,但接口允许多继承。
在接口的多继承中 extends 关键字只需要使用一次,在其后跟着要被继承的接口。如下所示:
public interface A {}
public interface B {}
public interface C extends A {}
public interface D extends A, B {}
implements
类实现接口:允许多个
当类实现接口的时候,类要实现接口中的所有方法。否则,类必须声明为抽象类。
class A [extends Parent] implements IA, IB, IC {
// 覆写接口中的所有抽象方法 or 声明为抽象类,实现部分方法
}
重写接口中声明的方法时,注意:
- 类在实现接口的方法时,不能抛出强制性异常。只能在接口中,或者继承接口的抽象类中抛出该强制性异常。
- 类在重写方法时,要保持一致的方法名,并且应该保持相同或者兼容的返回值类型。
- 如果实现接口的类时抽象类,那么就没必要实现该接口的方法。
在实现接口的时候,注意:
- 一个类只能继承一个类,但是可以实现多个接口。
- 一个接口能继承另一个接口,这和类之间的继承比较相似。