Java继承
继承是一个类获取另一类的成员(属性和方法)的过程,它是代码复用的一种手段。
继承其他类的类称为子类(派生类),被继承的类称为父类(基类)。
extends关键字
extends是用于继承类的关键字,以下是extends关键字的语法:
class Super { ..... ..... } class Sub extends Super { ..... ..... }
例子
以下是Java继承的示例,在此示例中,可以看到有两个类Calculation和My_Calculation。
My_Calculation使用extends关键字继承了Calculation类的方法addition()和Subtraction()。
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类的一个对象后,将在其中创建父类成员的副本,因此子类的对象可以访问父类的成员。
父类的变量可以保存子类对象,但是使用该变量只能访问父类的成员,因此,要访问两个类的成员,建议始终创建子类的变量。
如果考虑上述程序,可以按如下所示实例化该类,但是使用父类变量不能调用multiplication()方法,因为它属于子类My_Calculation。
Calculation demo = new My_Calculation(); demo.addition(a, b); demo.Subtraction(a, b);
注意:子类继承父类的所有成员(属性、方法和嵌套类)。构造函数不是成员,因此它们不会被子类继承,但是可以从子类中调用父类的构造函数。
super关键字
super关键字类似于this关键词,以下是使用super关键字的使用场景:
如果父类的成员和子类的成员有相同的名字,它被用来区分它们;
在子类中调用父类的构造函数。
区分成员
如果一个类继承了另一个类,并且父类的成员具有与子类相同的名称,为了区分这些成员,需要使用super关键字,如下所示。
super.variable super.method();
例子
在给定的程序中,有 Sub_class 和 Super_class两个类,都有一个名为display()的方法,但是具有不同的实现,还有一个名为num的变量,但是具有不同的值。我们调用两个类的display()方法,并打印两个类变量num的值。
可以观察到我们使用super关键字来区分父类和子类的成员。
复制并粘贴该程序到一个名为Sub_class.java的文件中:
class Super_class { int num = 20; //超类的显示方法 public void display() { System.out.println("This is the display method of superclass"); } } public class Sub_class extends Super_class { int num = 10; //子类的显示方法 public void display() { System.out.println("This is the display method of subclass"); } public void my_method() { //实例化子类 Sub_class sub = new Sub_class(); //调用子类的display()方法 sub.display(); //调用超类的display()方法 super.display(); //打印子类的变量num的值 System.out.println("value of the variable named num in sub class:"+ sub.num); //打印超类的变量num的值 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运算符用来检查一个类是否是另一个类的子类。
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 HAS-A Speed,通过为Speed设置单独的类,我们不必将属于speed的整个代码放入Van类中,这使得可以在多个应用程序中重用Speed类。
在面向对象的方法中,用户无需担心哪个对象正在执行实际工作,因此Van类向用户隐藏了实现细节。
继承类型
继承分为多继承和单继承,Java不支持多继承。这意味着一个类不能继承一个以上的类。因此以下行为是非法的:
public class extends Animal, Mammal{}
但是,一个类可以实现一个或多个接口,这帮助Java摆脱了多重继承的限制。