继承:
每一个扩展类继承基类都可以看成人类衍生出不同的人。
人的本能,都会通过语言交流、吃饭等。但是每个人说话的方式和吃饭方式会因为环境的不同而不同。
比如一个人,他说中文,他吃饭用的是筷子。另一个人,他说英语,他吃饭用刀叉。
都属于人类,拥有同样的行为,但是这些行为的实现方式都是不同的。
通过代码实现继承
/** * 父类 */ class People{ public void say(){ System.out.println("say"); } public void eat(){ System.out.println("eat"); } } /** * 子类 */ class YellowRace extends People{ } public class initBaseClass { public static void main(String[] args) { //继承的子类可以拥有父类的方法 YellowRace yellowRace = new YellowRace(); yellowRace.say(); yellowRace.eat(); } } /** * output: * say * eat */
继承父类的子类可以拥有父类的方法,这样黄种人(YellowRace)就有了人(People)的本能,但是现在黄种人拥有了自己的语言和吃饭的方式,原先人类的说话方式就会被丢弃,就在YellowRace这个类中重写人这个类中的方法,@Override这个注解是表明重写了下面的方法,当然也可以不写,将子类修改成下面的代码
/** * 子类 */ class YellowRace extends People{
@Override public void say(){ System.out.println("i speak chinese"); }
@Override public void eat(){ System.out.println("i eat with chopsticks"); } }
/** * output: * i speak chinese * i eat with chopsticks */
会了自己的说话方式,但是又不想忘记以前的交流方式,则通过super这个关键字去调用父类的方法,为什么不能直接调用方法,而要通过super去调用呢,因为直接调用方法会产生递归,变成死循环,所以java提供了super这个关键字去调用父类。修改子类方法
/** * 子类 */ class YellowRace extends People{ public void say(){ super.say(); System.out.println("i speak chinese"); } public void eat(){ super.eat(); System.out.println("i eat with chopsticks"); } } /** * output: * say * i speak chinese * eat * i eat with chopsticks */
现在的黄种人有了自己的说话方式和吃饭方式,突然发现这两个人的本能不够生存,现在需要学会走路去找吃的,即扩展继承的类
/**
* 父类
*/
class People{
public void say(){
System.out.println("say");
}
public void eat(){
System.out.println("eat");
}
}
/** * 子类 */ class YellowRace extends People{ public void say(){ System.out.println("i speak chinese"); } public void eat(){ System.out.println("i eat with chopsticks"); } public void walk(){ System.out.println("i walk to find food"); } } public class initBaseClass { public static void main(String[] args) { //继承的子类可以拥有父类的方法 YellowRace yellowRace = new YellowRace(); yellowRace.say(); yellowRace.eat(); yellowRace.walk(); } } /** * output: * i speak chinese * i eat with chopsticks * i walk to find food */
要注意的几个点:
1、子类在继承父类后,初始化时会先调用父类默认的无参构造方法,用来初始化方法和属性。
当父类定义一个有参构造方法,而子类继承后在构造方法中没有调用父类的有参构造方法,则会报错,因为子类默认调用父类的无参构造方法,要通过super去调用父类已定义的构造方法。
/** * 父类 */ class People{ public People(int i){ System.out.println("init People"); } } /** * 子类 */ class YellowRace extends People{ public YellowRace(int i) { super(i); System.out.println("init yellowRace"); } } public class initBaseClass { public static void main(String[] args) { YellowRace yellowRace = new YellowRace(1); } } /** * output: * init People * init yellowRace */
2、父类中的私有方法和私有属性,无法被子类继承,protected可以被继承并调用
/** * 父类 */ class People{ public People(int i){ System.out.println("init People"); } private void say(){ System.out.println("i speak"); } protected void walk(){ System.out.println("i walk"); } } /** * 子类 */ class YellowRace extends People{ public YellowRace(int i) { super(i); System.out.println("init yellowRace"); } } public class initBaseClass { public static void main(String[] args) { YellowRace yellowRace = new YellowRace(1); yellowRace.say();// 错误信息: The method say() from the type People is not visible 这个方法是不可见的,无法被子类调用 yellowRace.walk(); } } /** * output: * init People * init yellowRace * i walk */
3、当父类的第一个方法调用第二个方法,而子类覆写了第二个方法,创建子类后,则父类的第一个方法则会去调用被子类覆写的第二个方法。因为运行时,程序会先查找子类是否存在该方法,不存在则从父类中继承,子类拥有第二个方法,则会被调用。