Java 浅析三大特性之一继承

上文Java 浅析三大特性之一封装我们说到Java是一个注重编写类,注重于代码和功能复用的语言。Java实现代码复用的方式有很多,这里介绍一个重要的复用方式——继承。
在介绍继承之前,我们要明确一点,继承是一个比较复杂的编写类的方式,他会破坏掉父类的封装,因此只有我们确定需要用到继承的时候,我们才会用继承。

继承的概念

继承是一种构建新类的方式,他是基于已有的类的定义为基础,构建新的类,已有的类称为父类,新构建的类称为子类,子类能调用父类的非private修饰的成员,同时还可以自己添加一些新的成员,扩充父类,甚至重写父类已有的方法,更其表现符合子类的特征。让子类的表现更独特,更专业。

继承的写法

Java规定,一个类后面紧跟 extends关键字,再加一个类的名字,则表示新建的类继承自extends 后面的那个类。在我们上面这个文章最后,我们列举了一个类,代码如下:

public class Student {
    private String name;
    private String age;

    private String handleName(String name){
       return "I'm " + name;
    }

    private String handleAge(String age) {
        return age + " 岁";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = handleName(name);
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = handleAge(age);
    }
}

现在我们新建一个类去继承自他,这个类我们就叫Boys,其代码如下:

public class Boys extends Student {
    @Override
    public void setName(String name) {
        super.setName(name);
    }

    @Override
    public String getAge() {
        return super.getAge();
    }

    @Override
    public String getName() {
        return super.getName();
    }

    @Override
    public void setAge(String age) {
        super.setAge(age);
    }
}

在上面代码中,我们可以看到很多相似的方法,这些方法的方法签名,参数,返回类型都是与父类的方法是一致,Java允许我们定义和父类一致的方法,以便我们在这个方法中写入新的代码。上面方法中,我们会看见一个新的关键字super,这个关键字与this相似,不过super表明调用方法的对象是父类的对象,那这段自动生成的代码的意思就是如果我们不添加新的内容,那么当我们子类调用这些方法的时候,执行的是父类的方法。同时我们在这个方法上面看见一个注解 @Override这表明这个方法是覆盖父类的方法,而不是方法重载,下面我具体说一下什么是方法重载,以及这个注解存在的必要。

方法重载

方法重载是很有必要的一种方式,他其实体现的是一种多态。即我定义了一种方法,这个方法可以承接很多类型的参数,而不要针对每个参数定义不同的方法。其实构造器就是方法重载的一个典型应用,也因为构造器必须要根据不同的参数,构造不同的对象,所以必须要实现方法重载。
下面这个例子,我们看一下什么是重载

public class OverLoading {
    public void print(String args1) {
        System.out.println(args1);
    }

    public void print(String args1, String args2) {
        System.out.println(args1 + args2);
    }

    public void print(int args1) {
        System.out.println(args1);
    }

    public String print(double args1) {
        System.out.println(args1);
        return null;
    }

    //这不是方法重载,这是错误的语句
//    public String print(String args1) {
//        System.out.println(args1);
//        return null;
//    }

    public static void main(String[] args) {
        OverLoading ol = new OverLoading();
        ol.print(1.0);
        ol.print(1);
        ol.print("1");
        ol.print("1", "1");
    }

}

//输出结果
1.0
1
1
11

上面的代码当中,只有一个方法print,但这个方法却可以接受多种参数,甚至返回的类型也不一样,但是我们在测试时候发现,根据输入的不同,系统会自动执行不同的print。这就是方法的重载。注意上面我有一注释的语句,这个语句是错误的方法重载,所以我们要如何去区分方法的重载呢。
其实规则比较简单,每一个重载的方法必定有不同的参数列表。条件只有这一个。
第一个当中,参数列表是String args1,第二个参数列表是String args1, String args2,第三个参数列表是int args1,第四个参数列表是double args1。这四个,每一个参数的列表都是不一样的,所以他们是重载的方法,而第五个也就是说注释的语句显然参数列表是String args1与第一个是重复的,所以他不是方法重载,系统会直接报错,告诉你这个方法已经被定义了。甚至更极端的情况,参数的顺序都不一样,也算是方法重载,但在这个例子里,是不存在顺序不一样的,但下面这段代码算方法重载

  public String print(int args1, String args2) {
        return null;
    }

   public String print(String agrs2, int args1) {
        return null;
    }

这个看起来好像和继承没什么关系的知识点,但却并不是这样。因为子类会继承父类的非private方法,所以子类也会重载父类的方法。如果子类定义了一个方法签名和父类一致的方法,但参数列表不一样,这就算重载了父类的方法。但我们有时并不是要这样,我们更多的是希望子类定义一个和父类一样的方法签名和参数列表,而里面实现的功能不一样。这样的操作叫覆写。但有时会书写失误,所以我们会在覆写方法上加入@Override ,这样一旦我们写成了方法重载而非覆写就是报错。

继承的一些特点

在写完继承的写法之后,我们可以看出来一下继承的特点,第一,继承是有一个特殊的关键字super,第二,维持继承关系,我们可以用一个特殊的关键字protected这个上篇文章是讲过的,第三,很有意思的一点,子类其实可以看成一个特殊的父类,是父类的一种类型。下面我们具体的说一下每一点。

super关键字

super之前也提到过,是区别于this一种关键字,他一般表示的是调用方法的对象是父类的对象。那么我们就可以利用它去调用父类的方法,父类的非private的成员变量。当然他和this一样,也有一种特殊的应用,即用它去调用父类的构造器。一般情况在调用子类的构造器之前,会默认先调用父类的默认构造器,如果父类没有默认的构造器,那么我们在子类的构造器中就要明确用super去调用父类的构造器,否则会报错。例子如下:

public class Father {
    
    public Father(int a){
        System.out.println("这是父类的构造器");
    }
}

public class Son extends Father{
    public Son(){
        super(1);
    }
}

这里一定要显式的调用父类的构造器,否则编译器无法完成父类对象的构造。关于构造器的顺序,初始化过程等等我们以后再详细讨论。protected关键字我们在上篇文章中已经讲过,这里就不说了,我们主要说第三点,向上转型。

向上转型

我们使用继承,主要是因为父类和子类之间存在一个种所属关系,子类确实是父类的一种。比如我们可以把动物当做是父类,子类是猫,狗啊等等。猫,狗确实是动物的一种。动物所拥有的方法,猫,狗都有,所以猫,狗是一种类型的动物,既然如此,我们就可以把猫,狗向上转型成动物类型。这是安全且一定成功的。我们可以看下面的例子。

public class Animal {
    public void run(Animal animal) {
        System.out.println("动物在奔跑");
    }
}
public class Dog extends Animal{
    public static void main(String[] args) {
        Animal animal = new Animal();
        animal.run(new Dog());
    }
}

这里Animal类的run方法明确规定传入的参数是Animal类型,但我们传入Dog类型也是可以成功的。这种就是向上转型的一种应用。这种转型总是成功的原因,就是上面所说,Dog其实是比Animal更专业,更独特的类型,可以看做是一个专业的类型向通用的类型转换,由一个更大的类向更小的类转换,这种转换除了会丢失一些方法和属性以外,总会是成功的。关于向上转型还有很多要讲的内容,不过这都要和多态联系到一起,我们以后再说。

总结

继承提供了我们复用类和代码的一种方式,但他并不是唯一和最好的一种,当我们明确需要这种继承的关系去编写类的时候,或者我们需要用到向上转型的时候,我们才会用继承。如果不需要的话,我们可以考虑是不是还有其他的方法。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容