post10 继承的语法
举例如下:
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 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 package com.isflee.c06_2_1_detergent;class Cleanser { private String s = new String ("Cleanser" ); public void append (String a) { s += a; } public void dilute () { append(" dilute()" ); } public void apply () { append(" apply()" ); } public void scrub () { append(" scrub()" ); } public void print () { System.out.println(s); } public static void main (String[] args) { Cleanser x = new Cleanser (); x.dilute(); x.apply(); x.scrub(); x.print(); } } public class Detergent extends Cleanser { public void scrub () { append(" Detergent.scrub()" ); super .scrub(); } public void foam () { append(" foam()" ); } public static void main (String[] args) { Detergent x = new Detergent (); x.dilute(); x.apply(); x.scrub(); x.foam(); x.print(); System.out.println("Testing base class:" ); Cleanser.main(args); } }
关于继承的注意点:
1.在计划继承的时候,一个比较好的规则是将所有字段都设为private,并将 所有方法都设为public(protected 成员也允许衍生出来的类访问它;以后还会深入探讨这一问题)。
2.调用父类方法的时候,方法的定义(方法名和参数)相同时,子类中需要使用super关键字,防止与递归调用混淆。
3.进行继承时,我们并不限于只能使用基础类的方法。亦可在衍生出来的类里加入自己的新方法。这时采取的 做法与在普通类里添加其他任何方法是完全一样的:只需简单地定义它即可。
1.在衍生类的构建器中,Java会自动插入对基础类构建器的调用。
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 package com.isflee.c06_2_2_cartoon;class Art { Art() { System.out.println("Art constructor" ); } } class Drawing extends Art { Drawing() { System.out.println("Drawing constructor" ); } } public class Cartoon extends Drawing { Cartoon() { System.out.println("Cartoon constructor" ); } public static void main (String[] args) { Cartoon x = new Cartoon (); } }
2.含有自变量的构建器的初始化
编译器会强迫我们在衍生类构建器的主体中首先设置对基础类构建器的调用
如果类没有默认的自变量,或者想调用含有一个自变量的某个基础类构建器,必须明确地编写对基础类的调用代码。
用super关键字以及适当的自变量列表实现
使用代码如下:
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 package com.isflee.c06_2_3_chess;class Game { Game(int i) { System.out.println("Game constructor" ); } } class BoardGame extends Game { BoardGame(int i) { super (i); System.out.println("BoardGame constructor" ); } } public class Chess extends BoardGame { Chess() { super (11 ); System.out.println("Chess constructor" ); } public static void main (String[] args) { Chess x = new Chess (); } }
示例代码:
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 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 package com.isflee.c06_3_1_place_setting;class Plate { Plate(int i) { System.out.println("Plate constructor" ); } } class DinnerPlate extends Plate { DinnerPlate(int i) { super (i); System.out.println( "DinnerPlate constructor" ); } } class Utensil { Utensil(int i) { System.out.println("Utensil constructor" ); } } class Spoon extends Utensil { Spoon(int i) { super (i); System.out.println("Spoon constructor" ); } } class Fork extends Utensil { Fork(int i) { super (i); System.out.println("Fork constructor" ); } } class Knife extends Utensil { Knife(int i) { super (i); System.out.println("Knife constructor" ); } } class Custom { Custom(int i) { System.out.println("Custom constructor" ); } } public class PlaceSetting extends Custom { Spoon sp; Fork frk; Knife kn; DinnerPlate pl; PlaceSetting(int i) { super (i + 1 ); sp = new Spoon (i + 2 ); frk = new Fork (i + 3 ); kn = new Knife (i + 4 ); pl = new DinnerPlate (i + 5 ); System.out.println( "PlaceSetting constructor" ); } public static void main (String[] args) { PlaceSetting x = new PlaceSetting (9 ); } }
在自己的清除方法中,必须注意对基础类以及成员对象清除方法的调用顺序——假若一个子对象要以另一个为基础。
通常,应采取与C++编译器对它的“破坏器”采取的同样的形式: 首先完成与类有关的所有特殊工作(可能要求基础类元素仍然可见),然后调用基础类清除方法
举例:
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 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 package com.isflee.c06_3_2_cad_system;class Shape { Shape(int i) { System.out.println("Shape constructor" ); } void dispose () { System.out.println("Shape dispose" ); } } class Circle extends Shape { Circle(int i) { super (i); System.out.println("Drawing Circle" ); } void dispose () { System.out.println("Erasing Circle" ); super .dispose(); } } class Triangle extends Shape { Triangle(int i) { super (i); System.out.println("Drawing Triangle" ); } void dispose () { System.out.println("Erasing Triangle" ); super .dispose(); } } class Line extends Shape { private int start, end; Line(int start, int end) { super (start); this .start = start; this .end = end; System.out.println("Drawing Line: " + start + ", " + end); } void dispose () { System.out.println("Erasing Line: " + start + ", " + end); super .dispose(); } } public class CADSystem extends Shape { private Circle c; private Triangle t; private Line[] lines = new Line [3 ]; public CADSystem (int i) { super (i + 1 ); for (int j = 0 ; j < lines.length; j++) lines[j] = new Line (j, j * j); c = new Circle (1 ); t = new Triangle (1 ); System.out.println("Combined constructor" ); } public void dispose () { System.out.println("CADSystem.dispose()" ); t.dispose(); c.dispose(); for (int i = lines.length - 1 ; i >= 0 ; i--) lines[i].dispose(); super .dispose(); } public static void main (String[] args) { CADSystem x = new CADSystem (47 ); try { } finally { x.dispose(); } } }
原文
如果 Java 基础类 有一个方法名被“过载”使用多次,在衍生类里对那个方法名的重新定义就不会隐藏任何基础类的版本。
也就是说,
对于多级继承的情况,父类中的某个方法名被“过载”使用多次, 最后一级的子类的对象仍然能访问到父类的这个方法
代码如下:
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 package com.isflee.c06_3_3_hide;class Homer { char doh (char c) { System.out.println("doh(char)" ); return 'd' ; } float doh (float f) { System.out.println("doh(float)" ); return 1.0f ; } } class Milhouse {} class Bart extends Homer { void doh (Milhouse m) { } } class Hide { public static void main (String[] args) { Bart b = new Bart (); b.doh(1 ); b.doh('x' ); b.doh(1.0f ); b.doh(new Milhouse ()); } }