Java 继承
本文最后更新于:2024年3月18日 凌晨
Java 继承
- 继承是存在于面对对象程序中两个类之间的一种关系,被继承的类称为父类或超类,而继承父类的类称为子类,父类实际上是所有子类的公共域和公共方法的集合,而每个子类则是父类的特殊化,是对公共域和方法在功能,内涵方面的拓展和延伸,继承可使程序结构清晰,降低编码和维护的工作量。
- 定义类时通过extends关键字指明其要继承的直接父类,子类对象除了可以访问子类中直接定义的成员外,也可访问父类的所有非私有成员。
- 不妨以代表"像素"的Pixel类的设计为例,可能编写如下代码:
1 2 3 4 5 6
| class Pixel{ private int x; private int y; Color c; }
|
- 前面已编写过Point类,而像素是Point的一种特殊情况,利用继承机制可以将Pixel类的定义改动如下:
1 2 3 4
| class Pixel extends Point{ Color c; }
|
- 在Pixel类中只要定义颜色属性,其他属性从Point类继承,从而代码得以简化,用UML表示继承关系。
- 注意:通过类的继承,祖先类的所有成员均将成为子类拥有的"财富",但是能否通过子类对象直接访问这些成员则取决于访问权限的设置,例如,在子类中不能通过子类对象访问父类的私有属性,但并不意味着子类对象没有拥有该属性,可以通过其他一些公开方法间接存取该属性。
访问控制和继承
- 父类中声明为 public 的方法在子类中也必须为 public
- 父类中声明为 protected 的方法在子类中要么声明为 protected,要么声明为 public,不能声明为 private
- 父类中声明为 private 的方法,不能够被继承。
属性的继承
- 从父类继承的成员变量,其访问控制符仍然相同。
- 子类定义与父类同名的成员变量,并没有覆盖父类的成员变量,而是两个成员变量共存,默认情况下,父类的成员变量是被隐藏的,如果你非要调用父类的成员变量可使用super关键字。
静态属性方法的继承
- 静态属性和静态方法可以被继承,但是不是被重写(override)而是被隐藏,这是因为静态方法和属性是属于类的,调用的时候直接通过类名。方法名完成对,不需要继承机制及可以调用。
- 静态属性,静态方法和非静态的属性都可以被继承和隐藏而不能被重写,因此不能实现多态,不能实现父类的引用可以指向不同子类的对象,非静态方法可以被继承和重写,因此可以实现多态。
构造方法在类继承中的作用
- 构造方法不能继承,由于子类对象要对继承自父类的成员进行初始化,因此,在创建子类对象时除了执行子类的构造方法外,还需要调用父类的构造方法,具体遵循原则如下:
- 子类可以在自己构造方法中使用关键字
super()
来调用父类的构造方法,但super()
调用语句必须是子类构造方法中的第一个可执行语句。
- 子类在自己定义构造方法中如果没有用
super()
明确调用父类的构造方法,则在创建对象时,首先自动执行父类的无参构造方法,然后再执行自己定义的构造方法。
- 以下程序再编译时将出错,原因在于父类不含无参构造方法。
1 2 3 4 5
| class parent{ Stirng my; public parent(String x){ my = x; } } public clas subclass extends parent{ }
|
- 在parent类中由于定义了一个有参构造方法,所以系统不会自动产生产生无参构造方法,如果将有参构造方法注释掉,编译将可以通过。
- 鉴于上述情形,一个类在设计时如果有构造方法,最好提供一个无参构造方法了,因此,系统类库中的类大多提供了无参构造方法,用户编程时最好也养成此习惯。
[例6-1]:类的继承中构造方法的调用测试。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| class Point{ private int x,y;
public Point(int x,int y){ this.x = x; this.y = y; }
public Point(){ this(0,0); }
public String toString(){ String s = "点: "+x+","+y; return s; } }
public class Pixel extends Point{ Color c;
public Pixel(int x,int y,Color c){ super(x,y); this.c = c; }
public String toString(){ return super.toString()+"颜色:"+c; }
public static void main(String a[]){ Pixel x = new Pixel(3,24,Color.blue); System.out.println(x); } }
点: 3,24颜色:java.awt.Color[r=0,g=0,b=255]
|
- 说明:本例中两次出现super关键词,super与this在使用上有类似性,super表示当前对象的直接父类对象的引用,通过super除了可以调用父类的构造方法外,还可以通过super引用访问父类的属性和方法。
- 注意:使用this查找匹配的方法时首先在本类查找,在找不到时再到其父类和祖先类查找,使用super查找匹配方法时,首先到父类查找,如果不存在,则继续到其祖先类逐级往高层查找。
- 为了演示对父类无参构造方法的隐含调用,可以将Pixel的构造方法中含super调用的行注释掉,则程序运行结果将为:
1
| 点:0,0颜色:java.awt.color[r=0,g=0,b=255]
|
继承中父类和子类的初始化顺序
- 父类中静态成员变量和静态代码块。
- 子类中静态成员变量和静态代码块。
- 父类中普通成员变量和代码块,父类的构造函数。
- 子类中普通成员变量和代码块,子类的构造函数。