继承的出现是为了解决代码的复用,并且不破坏现有的程序代码。按照现有的类的类型来创建新类,无需改变现有类的形式,采用现有类的形式并在其中添加新代码。
1 、继承的实现是通过关键字extends,当这么做时,子类会自动的得到父类的所有域和方法(非private)。
2、在继承过程中,不一定非得使用父类的方法,也可以在子类中添加新的方法。
一、构造器 |
1、无参构造器:
java会自动在子类的构造器中对父类构造器的调用。例子如下:
class Art {
Art() {
System.out.println("Art 构造器");
}
}
class Drawing extends Art {
Drawing() {
System.out.println("Drawing 构造器");
}
}
public class Cartoon extends Drawing {
Cartoon() {
System.out.println("Cartoon 构造器");
}
public static void main(String[] args) {
Cartoon x = new Cartoon();
}
}
输出结果:
Art 构造器
Drawing 构造器
Cartoon 构造器
所以,父类在子类可以访问它之前,就已经完成了初始化,即使不创建Cartoon()构造器,也会生成一个默认构造器。
2、有参构造器:
上面的例子中的类都有默认的构造器,即这些构造器都没有参数,编译器可以轻松的调用它们是因为不用考虑参数的问题。如果没有默认的父类构造器,或者想要调用一个带参数的构造器,就必须用关键字super显示的编写调用父类构造器的语句,并且带有相应的参数
class Game {
Game(int i) {
System.out.println("Game 构造器");
}
}
class BaordGame extends Game {
BaordGame() {//这个构造器其实没什么价值
super(1);
System.out.println("Game 构造器");
}
BaordGame(int i) {
super(i);
System.out.println("Game 构造器");
}
}
小结:调用父类构造器必须是你在子类构造器中的第一件事,如果父类有默认的构造器,子类会默认的调用,如果父类没有默认的构造器,就必须用关键字super显示的调用父类构造器的语句,并且带有相应的参数
二、protected关键字 |
因为继承,protected关键字才有了意义。只有在理想状态下才仅靠关键字private,但在实际项目中,经常会把某些事物尽可能的隐藏,仍允许子类的成员访问它们。这个时候就需要使用到protected。
关键字protected,它指明“就类用户而言,这是private的,但对于任何继承于此类的子类或者其他任何位于同一个包内的类来说,它确是可以访问的。”
class Villain {
private String name;
public Villain(String name) {
this.name = name;
}
protected void set(String n) {
name = n;
}
public String toString() {
return "I am Villain and my name is " + name;
}
}
public class Orc extends Villain {
private int orcNumber;
public Orc(String name, int orcNumber) {
super(name);
this.orcNumber = orcNumber;
}
public void change(String name, int orcNumber) {
set(name);
this.orcNumber = orcNumber;
}
public String toString() {
return "Orc" + orcNumber + ": " + super.toString();
}
public static void main(String[] args) {
Orc orc = new Orc("Limburger", 12);
System.out.println(orc);
orc.change("Bob", 19);
System.out.println(orc);
}
}
由上可知,chenge()可以访问protected 的set()方法。
小结:尽管可以创建protected域,但是最好的方式还是将域保持为private,同样也要保持底层修改的权利;然后通过protcted方法来控制继承者的访问权限
三、向上转型 |
由子类转变成父类,在继承图上是向上移动的,一次一般称为向上转型。
class Instrument {
public void play() {}
static void tune(Instrument i) {
i.play();
}
}
public class Wind extends Instrument {
public void windPlay() {}
public static void main(String[] args) {
Wind w = new Wind();
Instrument.tune(w);// 向上转型
Instrument is = new Wind();
is.windPlay()//The method windPlay() is undefined for the type Instrument
}
}
小结:子类是父类的超集,它可能比父类含有更多的方法,必须具备父类中所含有的方法。在向上转型的过程中,类接口中唯一发生的事情就是丢失方法。这就是为什么编译器在“未曾明确表示转型”活“未曾指定特殊标记”的情况下,仍然允许向上转型的原因。
注意:到底是用组合还是继承,最简单的方法就是问一问自己是否需要从子类向父类进行向上转型。如果必须向上转型,则继承是必要的,但是如果不需要,则应当好好考虑自己是否需要继承。