代码很重要!!!其他都是废话。把代码看懂,最好自己写一遍。
继承。“在软件开发中继承就是子类可以使用从父类继承的属性和方法。”–百度百科。(开篇度娘来镇楼)作为面向对象三剑客,继承在OOP中举足轻重,对于代码复用就有重要意义。在学习继承时,老师都会由父类子类来反复讲解继承的概念及其中注意事项。很多人就在这辩证讲解中绕了进去。今天,就由3个Java例子来细细阐述继承的爱恨情仇。。。

一言不合就上码(PS–>张宇:上来!······)
ChineseFood.java

class Food{
    public Food() {
        System.out.println("食物  构造方法");
    }   
}
//中国菜继承Food
class ChineseFood extends Food{
    public ChineseFood() {
        System.out.println("中国菜  构造方法");
    }
    private String cFood = "中国菜";
    //此处 += 构成重载。 
    public void cook(String a){ cFood += a;}
    public void chao(){cook(" 炒");}
    public void shao(){cook(" 烧");}
    public void jian(){cook(" 煎");}
    public void zha(){cook(" 炸");}
    public String toString(){return cFood;}
    public static void main(String[] args){
        ChineseFood c = new ChineseFood();
        c.chao();
        c.shao();
        c.jian();
        c.zha();
        //由于toString()方法的存在下面调用时输出的不是ChineseFood对象。
        System.out.println(c);
    }
}

SichuanCuisine.java

//川菜继承中国菜
public class SichuanCuisine extends ChineseFood{
    public SichuanCuisine() {
        System.out.println("川菜  构造方法");
    }
    public void chao(){
        super.chao();
        cook(" 炒在川菜中演化出溜");
    }
    public void hua(){
        cook(" 滑");
    }
    public static void main(String[] args){
        SichuanCuisine s = new SichuanCuisine();
        s.chao();
        s.shao();
        s.jian();
        s.zha();
        //川菜有滑的烹饪方法。
        s.hua();
        //SichuanCuisine继承了ChineseFood,隐式的覆写了父类的toString()方法。
        System.out.println(s);
        System.out.println("测试中国菜:");
        //可以在一个类的方法中调用另一个类的主函数。
        ChineseFood.main(args);
    }
}
  • 以上两个Java文件中定义了三个类。SichuanCuisine类继承ChineseFood类,ChineseFood类继承Food类。下面就通过这个栗子来阐述继承。
  • 1、子类继承父类后,就会自动得到基类中所有的域和方法。SichuanCuisine继承了ChineseFood类,就会自动得到父类中的域和方法。所以,SichuanCuisine中没有显示定shao();jian();zha();的方法。但SichuanCuisine中第16行至18行可以调用这三个方法。
  • 2、子类可以具有父类没有的方法。例如:滑的烹饪方法是个别菜系的方法,而不是中国菜的共有方法。那么我们在代码中就要把这种子类特殊的方法写到子类中。对应的就是:SichuanCuisine类中定义了一个父类中没有的方法hua()。
  • 3、子类可以在覆写的父类方法中加入自己的特有逻辑。还是举菜的例子:在ChineseFood里chao()是各大菜系共有的方法,但川菜在传统炒的基础上发展处了“溜”的烹饪技巧。正如代码第6行至第9行方法中,子类覆写了父类chao()方法,带在其中又加入了自己特有的方法。
  • 4、Java会在父类的的构造函数中插入对子类构造函数的调用,父类在子类访问它之前就完成了初始化。为了方便大家理解,我把三个类的构造函数都显示地写了出来。SichuanCuisine第14行,在new出来对象s的时候,底层会先调用Food的构造函数,再调用ChineseFood的构造函数再调用SichuanCuisine的构造函数。这就是很多老师讲的:子类的实例化一定伴随父类的实例化。
  • 5、调用父类方法时用super。在SichuanCuisine的chao方法中想调用父类chao方法,就用super.chao();。
    这个栗子中还有三个值得深究的地方。就当是福利白送了。
  • A、ChineseFood.java第14行,中“+=”符号。很多初学者就把它理解为基本运算符中的“+=”,其实此“+=”非彼“+=”;此“李逵”非彼“李逵”。基本运算符运算的基本数据类型,String是基本数据类型嘛?其实这个“+=”是被Java设计者重载过的运算符。用来处理string对象的。
  • B、在ChineseFood.java中第26行及SichuanCuisine.java第22行,控制台输出的是一个对象,但实际输出的却不是对应对象的内存地址?留个白吧,来点神秘诱惑(把ChineseFood.java的第18行注释掉试一下),自己尝试去网上找资料解决问题,这是很重要的技能哦。请自行get!
  • C、掀开main的盖头来。在类中调用另外一个类的主函数。初始入门时,老师反复强调一个程序只有一个入口,所以很多同学都不约而同的会让自己的项目尽量保有一个main方法。好像main函数是什么洪水猛兽,令人敬而远之。再加上很多Demo中也都有这样的现象,令此甚嚣尘上!但main其实就是隔壁班的羞涩女孩,没有那么神秘。就像SichuanCuisine.java第25行,可以像普通的静态方法一样去调用她。其次,一个类即使不当做项目入口也可以给它一个main方法这种方法还有一个小用处。那就是方便测试。在测试工具泛滥的今天,但对于初学者这也不失一个方便上手的好方法:把mian方法当做单元测试的工具。比如:你写完一个类后,想知道该类有没有实现你需求的功能有没有BUG,可以在该类的main方法中调用来测试一下(本人初学Java时,找错误就是这么干的。插桩快乐!)。关于测试我想多说一点:很多开发者由于开发进度,人力各种原因都忽视测试,其实,测试本身就是软件开发的固有组成部分,神圣而不可忽视!初学者更应该有意思培养。
扩展了那么多,差点把继承都给忘了,那么再说一点继承吧。老规矩:一言不合就上码。

HunanCuisine.java

class FoodA{
    public FoodA(int i) {
        System.out.println("食物  构造方法");
    }   
}

class ChineseFoodA extends FoodA{
    ChineseFoodA(int i){
        super(i);
        System.out.println("中国菜  构造方法");
    }
}

public class HunanCuisine extends ChineseFoodA{
    HunanCuisine(){
        super(11);
        System.out.println("湘菜  构造方法");
    }
    public static void main(String[] args) {
        HunanCuisine h = new HunanCuisine();        
    }
}
亲!你上来了吗?开始说到继承的第4点时,将到了构造方法,其实还有一点值得注意。
  • 6、父类没有默认构造函数,子类必须显示地调用父类的构造函数,并且调用必须放到第一行。如:HunanCuisine.java中,FoodA中只要有参的构造函数,并且没有显示声明无惨的构造函数(可以理解为没有)。那么ChineseFoodA在继承的时候,就必须显示调用FoodA的构造函数。并且super()必须放到第一行。(可以尝试把它移到下面去看看。)
  • 当然,继承作为OOP三剑客不是这三言两语就能完全说完的,正如BAT都不是喷出的。继承还有其他内容,以后再说。

代码很重要!!!其他都是废话。把代码看懂,最好自己写一遍。