java 中的继承

本贴最后更新于 2019 天前,其中的信息可能已经渤澥桑田

什么是继承?

在 java 中,难免会出现有很多类具有相同的数据和行为,它们甚至在抽象层面可以归为同一个种类。既然具有相同的数据和行为,那么我们在定义这些类的时候也会重复性的去声明这些数据和行为。为了方便,我们可以把这些相同的数据和行为抽出来放在单独的一个类里,我们称这个类为父类,任何想要具有父类据和行为的类可以通过继承来得到,通过继承得到数据和行为的类,我们称这些类为子类。

定义父类和子类

定义父类非常简单,和定义一个普通的类一样,只是这个父类封装了会重复性的数据和行为。
定义一个子类也非常简单,使用 extends 关键字即可。

/** 
 *   子类名称 extends  父类名称 
 *    狗类继承了动物类,狗也是动物
 */
 public class Dog extends Animal{
    
 }

方法覆盖

方法覆盖也叫方法重写。虽然父类封装了相同的行为,但子类们有时候面对某一种相同的行为表现的却各不相同。
比如猫和狗都继承了动物,动物都具有叫的行为,但猫叫和狗叫就不相同。所以我们就可以说猫和狗重写了叫的行为。

public class Animal {   
    /**     
    *     叫的行为     
    */   
    public void call(){       
        //父类是抽象的,我们不知道“动物”怎么叫,就给它一个空的实现                                 
        System.out.println("");    
    }
 }
public class Dog extends Animal {    
    /**     
     * 覆盖(重写)叫的方法     
     */    
    @Override    
    public void call() {        
        System.out.println("汪汪汪");   
    }
}
public class Cat extends Animal {    
    /**     
     * 覆盖(重写)叫的方法     
     */    
    @Override    
    public void call() {        
        System.out.println("喵喵喵");   
    }
}

子类构造器

构造器也称构造方法,是用来构造对象的,new 关键字其实就是调用构造器。
构造器被调用的时候还要完成对成员变量的赋值,如果是无参构造器,则根据每个成员变量的类型赋予默认值。

由于子类不能访问父类的私有成员,所以子类构造方法在执行的时候必须先调用父类构造器,优先完成对父类私有成员的赋值。 不然,那些复用的数据没有值,那也就没什么意义了。

实例化一个对象的过程如下:
1.首先根据 new 关键字来调用指定的构造器来创建对象。
2.如果是无参构造器,首先先调用父类的无参构造器,再调用子类的无参构造器
3.如果是有参构造,首先先调用父类的有参构造器,再调用子类的有参构造器

多态

字义就很容易理解,多种形态,动物可以是狗,可以是猫,也可以是其他任何动物
那么,我们是不是可以这么来写代码呢。
Animal animal = new Dog();
Animal animal = new Cat();

这就是多态,子类的对象可以使用父类的类型来接收,反之则不可以,我们可以说狗是一只动物,却不可以说动物是一只狗,这样显得就很奇怪。

优点
多态可以使我们动态决定自己想要什么,想要狗就是狗,想要猫就是猫。由此可知多态十分灵活,特别容易扩展和复用。
Animal animal = new Dog();
animal = new Cat();

缺点
Animal animal = new Dog();
此时,animal 的类型虽然是 Dog,但 animal 归根结底是父类的引用指向了子类,所以 animal 不能访问 Dog 的成员和方法。
其实,也算不上什么缺点。

阻止继承

有了继承和多态带来的好处,那么我们是不是可以去随便继承,随便复用代码。
那显然是不行的,java 的继承是单继承,这本身就告诉我们继承要有意义的去继承,不能看见谁都要认“祖宗”,这样会造成一个类混乱和复杂,职责不明确,导致我们不知道这个类到底要干什么。
也可以使用 final 关键字来限制别的类去继承和重写某些重要的方法,导致方法本身的含义被破坏。

final 关键字就保证了类不允许被继承

抽象类

还记得方法重写的时候,有这么一段代码

public class Animal {   
    /**     
    *     叫的行为     
    */   
    public void call(){       
        //父类是抽象的,我们不知道“动物”怎么叫,就给它一个空的实现                            
    }
 }

父类都是抽象出来的,继承链中越往上越抽象,往往抽象的父类并不需要有具体的实例对象,只是为了达到子类能复用的目的,在面对可以有多种表现的行为方法,父类也并不知道怎么去实现,如上面代码所示,即便实现也只是一个空的方法,面对这种情况,抽象类就诞生了。

抽象类的定义

使用 abstract 关键字来定义一个抽象类

public abstract class Animal{
    public abstract void call();
}

在有抽象方法的时候,必须声明类为抽象类,且抽象类不能被实例化,抽象方法必须被重写。

Object 类

Object 类是 java 中所有类的始祖,是所有类的父类,每个类都是由它扩展而来。
虽然每个类并没有使用 extends Obejct 去继承 Object,但如果这个类没有明确指出其父类,那这个类就默认继承了 Object。

仅为本人复习笔记,复习自 java 核心技术卷 1

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3186 引用 • 8212 回帖 • 1 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...