继承可以定义为一个类获取另一个类的属性(方法和字段)的过程。 通过使用继承,可以按层次顺序管理信息。
继承其他类的属性的类称为子类(或派生类),被其它继承其属性的类称为超类(或基类,父类)。
1. extends关键字
extends
是用于继承类属性的关键字。 以下是extends
关键字的语法。
语法
class Super {
.....
.....
}
class Sub extends Super {
.....
.....
}
示例代码
以下是演示Java继承的示例。 在此示例中,可以观察两个类,即Calculation
和MyCalculation
。
使用extends
关键字,MyCalculation
继承Calculation
类的方法:addition()
和Subtraction()
。
将以下程序复制并粘贴到名为MyCalculation.java 的文件中。
// 文件:MyCalculation.java
class Calculation {
int z;
public void addition(int x, int y) {
z = x + y;
System.out.println("两个数的和是:" + z);
}
public void Subtraction(int x, int y) {
z = x - y;
System.out.println("两个数的差是:" + z);
}
}
public class MyCalculation extends Calculation {
public void multiplication(int x, int y) {
z = x * y;
System.out.println("两个数的乘积是:" + z);
}
public static void main(String args[]) {
int a = 20, b = 10;
MyCalculation demo = new MyCalculation();
demo.addition(a, b);
demo.Subtraction(a, b);
demo.multiplication(a, b);
}
}
执行上面示例代码,得到以下结果:
两个数的和是:30
两个数的差是:10
两个数的乘积是:200
在给定的程序中,当创建MyCalculation
类的对象时,会在对象内部创建超类(Calculation
)的内容的副本。就可以使用子类的对象,来访问超类的成员。
超类引用变量可以包含子类对象,但是使用该变量只能访问超类的成员,因此要访问两个类的成员,建议始终为子类创建引用变量。
如果考虑上面的程序,可以实例化下面给出的类。 但是使用超类引用变量(在本例中为cal
),无法调用方法multiplication()
,因为方法multiplication()
属于子类MyCalculation
的方法。
注 - 子类从超类继承所有成员(字段,方法和嵌套类)。构造函数不是成员,因此它们不能被子类继承的,但是可以从子类调用超类的构造函数。
2. super关键字
super
关键字与this
关键字类似,以下是使用super
关键字的注意事项。
- 如果它们具有相同的名称,
super
与this
关键字用于区分超类的成员和子类的成员。 super
关键字用于从子类调用超类构造函数。
区分成员
如果一个类继承了另一个类的属性。如果超类的成员具有与子类相同的名称,要区分这些变量,使用super
关键字显示地访问父类的属性,如下所示 -
super.variable; // 访问父类变量
super.method();// 访问父类方法
示例代码
本节提供了一个演示如何使用super
关键字用法的程序。
在给定的程序中有两个类,即Subclass
和Superclass
,它们都有一个名为display()
的方法,具有不同的实现,以及一个num
变量,具有不同的值。 调用两个类的display()
方法并打印两个类的变量num
的值。 在这里,使用super
关键字来区分超类和子类的成员。
将程序复制并粘贴到名为Subclass.java
的文件中。
// Subclass.java
class Superclass {
int num = 20;
// 超类方法
public void display() {
System.out.println("这是超类的显示方法");
}
}
public class Subclass extends Superclass {
int num = 10;
// 子类方法
public void display() {
System.out.println("这是子类的显示方法");
}
public void my_method() {
// 初始化子类
Subclass sub = new Subclass();
// 调用子类的display()方法
sub.display();
// 调用父类的display()方法
super.display();
// 打印子类变量num的值
System.out.println("子类中名为num的变量的值:" + sub.num);
// 打印父类变量num的值
System.out.println("超类中名为num的变量的值:" + super.num);
}
public static void main(String args[]) {
Subclass obj = new Subclass();
obj.my_method();
}
}
执行上面示例代码,得到以下结果:
这是子类的显示方法
这是超类的显示方法
子类中名为num的变量的值:10
超类中名为num的变量的值:20
3. 调用超类构造函数
如果一个类继承另一个类的属性,则子类自动获取超类的默认构造函数。 但是如果要调用超类的参数化构造函数,则需要使用super
关键字,如下所示。
super(parm-values);
示例代码
下面给出的程序中演示了如何使用super
关键字来调用超类的参数化构造函数。 这个程序包含一个超类和一个子类,超类中包含一个接受整数值的参数化构造函数,在子类中使用super
关键字来调用超类的参数化构造函数。
将以下程序复制并粘贴到名为Subclass.java 的文件中 -
// Subclass.java
class Superclass {
int age;
Superclass(int age) {
this.age = age;
}
public void getAge() {
System.out.println("超类中名为age的变量的值是: " + age);
}
}
public class Subclass extends Superclass {
Subclass(int age) {
super(age);
}
public static void main(String argd[]) {
Subclass s = new Subclass(24);
s.getAge();
}
}
执行上面示例代码,得到以下结果:
超类中名为age的变量的值是: 24
4. IS-A关系
IS-A是这样的一种说法:对象A
是对象B
的一种。下面来看看如何使用extends
关键字实现继承。
public class Animal {
}
// Mammal IS-A Animal
public class Mammal extends Animal {
}
// Reptile对象是(IS-A)对象 Animal 的一种
public class Reptile extends Animal {
}
// Dog对象是(IS-A)对象 Mammal 的一种
public class Dog extends Mammal {
}
基于上面的例子,在面向对象的术语中,以下是真的 -
- 动物(
Animal
)类是哺乳动物(Mammal
)类的超类。 - 动物(
Animal
)类是爬行动物(Reptile
)类的超类。 - 哺乳动物(
Mammal
)类和爬行动物(Reptile
)是Animal
类的子类。 - 狗(
Dog
)是哺乳动物(Mammal
)类和动物(Animal
)类的子类。
现在,如果使用IS-A关系,可以这样描述 -
Mammal
IS-AAnimal
Reptile
IS-AAnimal
Dog
IS-AMammal
- 因此:
Dog
IS-AAnimal
通过使用extends
关键字,子类将能够继承超类的所有属性,但超类的私有属性除外。可以确保Mammal
使用instanceof
运算符来判断它是Animal
类型。
示例代码
class Animal {
}
class Mammal extends Animal {
}
class Reptile extends Animal {
}
public class Dog extends Mammal {
public static void main(String args[]) {
Animal a = new Animal();
Mammal m = new Mammal();
Dog d = new Dog();
System.out.println(m instanceof Animal);
System.out.println(d instanceof Mammal);
System.out.println(d instanceof Animal);
}
}
执行上面示例代码,得到以下结果:
true
true
true
通过上面的学习,现在对extends
关键字应该有很好的理解了,下面来看看implements
关键字如何用于获取IS-A 关系。
通常,implements
关键字与类一起用于继承接口的属性。 接口永远不能被类扩展。
示例
public interface Animal {
}
public class Mammal implements Animal {
}
public class Dog extends Mammal {
}
4.1. instanceof关键字
使用instanceof
运算符来检查确定Mammal
是否是Animal
类的一种,Dog
是否是Animal
类的一种。
示例
interface Animal{}
class Mammal implements Animal{}
public class Dog extends Mammal {
public static void main(String args[]) {
Mammal m = new Mammal();
Dog d = new Dog();
System.out.println(m instanceof Animal);
System.out.println(d instanceof Mammal);
System.out.println(d instanceof Animal);
}
}
执行上面示例代码,得到以下结果:
true
true
true
5. HAS-A关系
这些关系主要基于用法。 这决定了某某类HAS-A
是否有某种东西。这种关系有助于减少代码重复和错误。
示例
public class Vehicle{}
public class Speed{}
public class Van extends Vehicle {
private Speed sp;
}
上面示例中Vehicle
类有HAS-A Speed
类。 通过为Speed
提供一个单独的类,不必将属于Speed
类的整个代码放在Van
类中,这样就可以在多个应用程序中重用Speed
类。
在面向对象的功能中,用户无需担心哪个对象正在进行实际工作。要实现这一点,Van
类隐藏了用户的实现细节。 因此,基本上发生的事情是用户会要求Van
类执行某个操作,而Van
类要么自己完成工作要么要求另一个类执行操作。
6. 继承的类型
如下所示,有各种各样类型的继承。
需要注意:Java不支持多重继承。 在Java中,一个类不能扩展多个类。 因此以下代码是非法的 -
// 非法声明类
public class extends Animal, Mammal{}
但是,一个类可以实现一个或多个接口,这有助于Java实现多重继承特性。