关于继承的一些知识

来源:互联网 发布:朝鲜核试验 知乎 编辑:程序博客网 时间:2024/06/05 04:32

考虑继承时值得注意的几点

  • 和传统的理解相反,子类并不是父类的一个子集。实际上,一个子类通常比它的父类包含更多的信息和方法。
  • 父类中的私有数据域在该类之外是不可访问的。因此,不能在子类中直接使用它们。但是,如果父类中定义了公共的访问器/修改器,那么可以通过这些公共的访问器/修改器来访问和修改它们。
  • 不是所有的“是”关系(is-a)都该用继承来建模。例如:一个正方形是一个矩形,但是不应该定义一个Square类来扩展Rectangle类,因为没有任何东西可以从矩形扩展(或者补充)到正方形。所以,应该定义一个扩展自GeometricObject类的Square类。如果要用类B去扩展类A,那么A应该要比B包含更多的信息。
  • 继承是用来为“是”关系(is-a)建模的。不要仅仅为了重用方法这个原因而盲目地扩展一个类。例如:尽管Person类和Tree类可以共享类似高度和重量这样的通用特性,但是从Person类扩展出Tree类是毫无意义的。一个父类和它的子类之间必须存在“是”关系。
  • 某些程序设计语言是允许从几个类派生出一个子类的。这种能力称为多重继承。但是在Java中,是不允许多重继承的。一个Java类只可能直接继承自一个父类。这种限制称为单一继承。如果使用extends关键字来定义一个子类,它只允许有一个父类。然而,多重继承是可以通过接口来实现的。

构造方法链

在任何情况下,构造一个类的实例时,将会调用沿着继承链的所有父类的构造方法。如果父类继承自其他类,那么父类构造方法又会在完成自己的任务之前,调用它自己的父类的构造方法。这个过程持续到沿着这个继承体系结构的最后一个构造方法被调用为止。这就是构造方法链。

例如下面的代码:

 

public class Faculty extends Employee {   public static void main(String[] args){      new Faculty();   }   public Faculty() {      System.out .println("(4)Performs Faculty's tasks");   }}class Employee extends Person {   public Employee() {      this("(2) Invoke Employee's overloaded constructor");      System.out.println("(3) {erforms Employee's tasks ");   }   public Employee(String s) {      System.out.println(s);   }}class Person {   public Person() {      System.out.println("(1) Performs Person's tasks");   }}

 

 输出:

 

(1) Performs Person's tasks(2) Invoke Employee's overloaded constructor(3) Performs Employee's tasks(4) Performs Faculty's tasks

 

 在第3行,new Faculty()调用Faculty的无参构造方法。由于Faculty是Employee的子类,所以,在Faculty构造方法中的所有语句执行之前,先调用Employee的无参构造方法。Employee的无参构造方法调用Employee的第二构造方法(第12行)。由于Employee是Person的子类,所以,在Employee的第二个构造方法中所有语句执行之前,先调用Person的无参构造方法。

 

覆盖方法

子类从父类中继承方法,有时,子类而要修改父类中定义的方法的实现,这称做方法覆盖。

GeometricObject类中的toString方法返回表示几何对象的字符串。这个方法可以被覆盖,返回表示圆的字符串。为了覆盖它,如下代码:

 

public class Circle extends GeometricObject {   public String toString() {      return super.toString() + "\n radius is " + radius;   }}

 

 toString()方法在GeometricObject类中定义,在Circle类中修改。在这两个类中定义的该方法都可以在Circle类中使用。要在Circle类中调用定义在GeometricObject中的toString方法,使用super.toString()(第3行)。

Circle的子类不能用语法super.super.toString()访问定义在GeometricObject中的toString方法。这是一个语法错误。

以下几点值得注意:

 

  • 仅当实例方法是可访问时,它才能被覆盖。这样,因为私有方法在它的类本身以外是不能访问的,所以它不能被覆盖。如果子类中定义的方法在父类中是私有的,那么这两个方法完全没有关系。
  • 与实例方法一样,静态方法也能被继承。但是,静态方法不能被覆盖。如果父类中定义的静态方法在子类中被重新定义,那么定义在父类中的静态方法将被隐藏。可以使用语法:父类名.静态方法名 调用隐藏的静态方法。