Java 继承
继承可以定义为一个类获取另一类的属性(方法和字段)的过程。通过使用继承,信息可以按照层次结构进行管理。
继承其他类属性的类被称为子类(派生类、子类),而被继承属性的类被称为超类(基类、父类)。
extends关键字
extends 是用于继承类属性的关键字。以下是extends关键字的语法。
语法
class Super {
.....
.....
}
class Sub extends Super {
.....
.....
}
样例代码
以下是一个演示Java继承的示例。在这个示例中,你可以观察到两个类,即Calculation和My_Calculation。
使用extends关键字,My_Calculation类继承了Calculation类的addition()和Subtraction()方法。
将以下程序复制粘贴到一个名为My_Calculation.java的文件中。
示例
class Calculation {
int z;
public void addition(int x, int y) {
z = x + y;
System.out.println("The sum of the given numbers:"+z);
}
public void Subtraction(int x, int y) {
z = x - y;
System.out.println("The difference between the given numbers:"+z);
}
}
public class My_Calculation extends Calculation {
public void multiplication(int x, int y) {
z = x * y;
System.out.println("The product of the given numbers:"+z);
}
public static void main(String args[]) {
int a = 20, b = 10;
My_Calculation demo = new My_Calculation();
demo.addition(a, b);
demo.Subtraction(a, b);
demo.multiplication(a, b);
}
}
如下所示,编译并执行上述代码。
javac My_Calculation.java
java My_Calculation
执行程序后,将产生以下结果−
输出
The sum of the given numbers:30
The difference between the given numbers:10
The product of the given numbers:200
在给定的程序中,当创建 My_Calculation 类的对象时,会在其中创建一个超类内容的副本。这就是为什么可以使用子类的对象来访问超类的成员。
超类引用变量可以持有子类对象,但使用该变量只能访问超类的成员,所以为了访问两个类的成员,建议总是创建子类的引用变量。
如果考虑上述程序,可以按照下面给出的方式实例化该类。但是,使用超类引用变量(在这种情况下是 cal )无法调用属于子类 My_Calculation 的方法 multiplication() 。
Calculation demo = new My_Calculation();
demo.addition(a, b);
demo.Subtraction(a, b);
注意 − 子类会继承其父类的全部成员(字段、方法和嵌套类)。构造函数不是成员,所以子类不会继承构造函数,但是可以从子类中调用父类的构造函数。
super关键字
super 关键字类似于 this 关键字。以下是使用super关键字的场景。
- 当父类和子类拥有相同名称的成员时,它用于将父类的成员与子类的成员区分开。
-
用于从子类中调用父类的构造函数。
区分成员
如果一个类继承了另一个类的属性,并且父类的成员与子类的成员具有相同的名称,为了区分这些变量,我们使用super关键字,如下所示。
super.variable
super.method();
示例代码
本节提供一个程序示例,演示了 super 关键字的用法。
在给定的程序中,有两个类,分别是 Sub_class 和 Super_class ,它们都有一个名为 display() 的方法,具有不同的实现,以及一个名为 num 的变量,具有不同的值。我们调用了两个类的 display() 方法,并打印了两个类的 num 变量的值。在这里,您可以观察到我们使用了 super 关键字来区分超类和子类的成员。
将该程序复制粘贴到名为 Sub_class.java 的文件中。
示例
class Super_class {
int num = 20;
// display method of superclass
public void display() {
System.out.println("This is the display method of superclass");
}
}
public class Sub_class extends Super_class {
int num = 10;
// display method of sub class
public void display() {
System.out.println("This is the display method of subclass");
}
public void my_method() {
// Instantiating subclass
Sub_class sub = new Sub_class();
// Invoking the display() method of sub class
sub.display();
// Invoking the display() method of superclass
super.display();
// printing the value of variable num of subclass
System.out.println("value of the variable named num in sub class:"+ sub.num);
// printing the value of variable num of superclass
System.out.println("value of the variable named num in super class:"+ super.num);
}
public static void main(String args[]) {
Sub_class obj = new Sub_class();
obj.my_method();
}
}
使用以下语法编译和执行上述代码。
javac Super_Demo
java Super
执行程序后,您将获得以下结果−
This is the display method of subclass
This is the display method of superclass
value of the variable named num in sub class:10
value of the variable named num in super class:20
调用超类构造函数
如果一个类继承另一个类的属性,子类会自动继承超类的默认构造函数。但是如果你想调用超类的带参数的构造函数,你需要使用super关键字,如下所示。
super(values);
示例代码
本节中给出的程序演示了如何使用super关键字调用超类的有参构造方法。该程序包含一个超类和一个子类,其中超类包含一个接受整数值的有参构造方法,我们使用super关键字调用了超类的有参构造方法。
将以下程序复制粘贴到名为Subclass.java的文件中
示例
class Superclass {
int age;
Superclass(int age) {
this.age = age;
}
public void getAge() {
System.out.println("The value of the variable named age in super class is: " +age);
}
}
public class Subclass extends Superclass {
Subclass(int age) {
super(age);
}
public static void main(String args[]) {
Subclass s = new Subclass(24);
s.getAge();
}
}
使用以下语法编译并执行上面的代码。
javac Subclass
java Subclass
在执行程序时,您将得到以下结果−
输出
The value of the variable named age in super class is: 24
IS-A关系
IS-A是一种说法:这个对象是那个对象的一种类型。让我们看看如何使用 extends 关键字实现继承。
public class Animal {
}
public class Mammal extends Animal {
}
public class Reptile extends Animal {
}
public class Dog extends Mammal {
}
现在,根据以上示例,可以用面向对象的术语来说以下内容是正确的 −
- Animal 是 Mammal 类的父类。
- Animal 是 Reptile 类的父类。
- Mammal 和 Reptile 是 Animal 类的子类。
- Dog 是 Mammal 和 Animal 类的子类。
现在,如果考虑IS-A关系,我们可以说 −
* Mammal IS-A Animal
* Reptile IS-A Animal
* Dog IS-A Mammal
* 因此:Dog IS-A Animal。
通过使用extends关键字,子类将能够继承父类的所有属性,除了父类的私有属性。 我们可以通过使用实例运算符来确保Mammal实际上是一个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 {
}
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
HAS-A关系
这些关系主要是基于使用。这确定了某个类是否具有某个东西。 HAS-A 这种关系有助于减少代码重复和错误。
让我们看一个示例-
示例
public class Vehicle{}
public class Speed{}
public class Van extends Vehicle {
private Speed sp;
}
这表明Van类具有Speed的属性。通过将Speed作为一个独立的类,我们不需要将整个属于Speed的代码放在Van类中,这样可以在多个应用程序中重用Speed类。
在面向对象的特性中,用户不需要关心哪个对象在执行真正的工作。为了实现这一点,Van类隐藏了Van类的使用者不需要关心的实现细节。因此,基本上用户会要求Van类执行某个操作,Van类要么自己执行这项工作,要么要求另一个类执行该操作。
继承的类型
下面展示了几种继承的类型。
一个非常重要的事实是Java不支持多重继承。这意味着一个类不能继承超过一个类。因此以下是非法的:
示例
public class extends Animal, Mammal{}
然而,一个类可以实现一个或多个接口,这帮助Java摆脱了多重继承的限制。