继承
当一个类继承其它类时,会自动获得基类中所有的域和方法
当基类Cleanser中的scrub为private时,子类super.scrub()无法访问父类中的方法,但是由于子类继承了父类的所有方法,所以子类main方法中的对象可以访问scrub()
class Cleanser {
private String s = "Cleanser";
public void append(String a) { s += a; }
public void dilute() { append(" dilute()"); }
public void apply() { append(" apply()"); }
public void scrub() { append(" scrub()"); }
public String toString() { return s; }
public static void main(String[] args) {
Cleanser x = new Cleanser();
x.dilute(); x.apply(); x.scrub();
System.out.println(x);
}
}
public class Detergent extends Cleanser {
// Change a method:
public void scrub() {
append(" Detergent.scrub()");
super.scrub(); // Call base-class version,当父类scrub为private时无法访问
}
// Add methods to the interface:
public void foam() { append(" foam()"); }
// Test the new class:
public static void main(String[] args) {
Detergent x = new Detergent();
x.dilute();
x.apply();
x.scrub();
x.foam();
System.out.println(x);
System.out.println("Testing base class:");
Cleanser.main(args);
}
}
如果没有加任何访问权限修饰词,那么成员默认的访问权限是包访问权限,仅允许包内成员访问。因此,在此包中,如果没有访问权限,任何人都可以使用这些方法。
为了继承,一般是将所有数据成员都指定为private,将所有方法都指定为public。
带参数构造器
上例中各个类均含有默认构造器,编译器可以轻松调用它。但是如果没有默认的基类构造器,或者想调用一个带参数的构造器,那么就要用super
1)如果基类构造器中同时存在默认构造器和参数构造器,那么子类构造器若想调用其参数构造器,则必须使用super(),若不使用super(),那么就会调用默认构造器。
2)若基类中只有参数构造器,那么不管需不需要调用构造器,必须使用super()
3)若调用参数构造器,那么必须在子类构造器开头中用super()
4)super()表示调用父类中的成员,super()无参数表示调用父类默认构造器。
5)若想调用父类的方法,可以super.方法名,也可以直接使用父类名字
import Access.IceCream;
class Game {
Game(String i) {
System.out.println("Game constructor");
}
Game() {
System.out.println("1111Game constructor");
}
}
class BoardGame extends Game {
BoardGame(String i) {
//super(i);
//super();这样也可以表示调用父类默认构造器
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();
}
}
向上转型
由于导出类可以调用基类的所有方法和域,那么向基类发出的信息同样也可以向导出类发出,那么可以意味着导出类的对象也是一种类型的基类。
在基类的tune()方法中,程序代码可以对Instrument和它的所有导出类起作用,这种将Wind引用转换为Instrument引用的动作,我们称之为向上转型
由于基类中tune()方法为static,所以要通过类名.方法名访问。
要是基类tune()方法为非static,这只可以对象名.方法名访问.
class Instrument {
public void play() {}
static void tune(Instrument i) {
// ...
System.out.println("yes");
i.play();
}
}
public class Wind extends Instrument {
public static void main(String[] args) {
Wind flute = new Wind();
Wind.tune(flute); // Upcasting
}
}