阅读 30

java-面向对象编程--继承

从常识中我们知道货车、轿车、suv、卡车…,它们都是车,而且都有一些共性,有名字、载客量、年龄等等,而且它们都能够加油、运东西等等共同的行为,所以从这里我们可以发现他们都拥有车的属性和行为,同时也是从车那里继承来的这些属性和行为的。

首先,什么叫继承呢?从上面我们就可以基本了解了继承的概念了,从理解上来说就是儿子获得了父亲所有的东西,并且这些东西是属于儿子的,儿子可以随意支配。那么从编程语言角度出发,就是一个类获取了另外一个类的全部方法,并且对这些方法进行自主的支配。在这里,被别人继承的类,我们叫父类,也叫超类或者基类。而继承了父类的类呢,就叫子类,也叫派生类,子类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。借助一个关键字extends,它的作用是声明父类。通过使用继承我们能够非常方便地复用以前的代码,能够大大的提高开发的效率。

父类 Vehicle

public class Vehicle {
    protected String name;
    protected int age;
    protected int carriageWheel
    protected int busload(){
       System.out.println("能坐两人")
       return 20;
    }
}复制代码

子类 Car

public class Car extends Vehicle {
    private String engine;
    protected int busload(){
       System.out.println("能坐四人")
       return 4;
    }
}
复制代码

子类Train

public class Train extends Vehicle {
    private String engine;
    protected int busload(){
       System.out.println("能坐两百人")
       return 200;
    }}复制代码

对于Car 和 Train 使用继承后,除了代码量的减少我们还能明显的看到他们关系。当我们在继承一个父类的时候,可以根据实际需要对父类中的方法进行重写,从而获取实际所需要的实现步骤 。同时,也可以在父类方法的基础上进行扩充 。在子类中可以增加域,增加方法或者覆盖父类的方法,然而绝对不能删除继承任何域的方法。

是我们在开发过程中是经常会用到继承的。所以掌握其特性对于一个开发者而言,是很必要的。最基础的需求,也是在开发的过程中知道需不需要继承,什么时候继承,为什么要继承,怎样去继承。也就是说,在开发的过程中,最后将这四个问题重复地问自己,这样的话可能会加深对继承的应用技巧哦。

同时在使用继承时需要记住三句话:

1、子类拥有父类非private的属性和方法。

2、子类可以拥有自己属性和方法,即子类可以对父类进行扩展。

3、子类可以用自己的方式实现父类的方法。

is-a 关系

 继承所描述的是“is-a”的关系,如果有两个对象D和B,换句话说,通常"is aB"(BD包含在内,或是D被包含在B内)指的是,概念体D物是概念体B物的特殊化,而概念体B物是概念体D物的一般化。举例来说,水果苹果橘子芒果与其他水果的一般化。则可以表示D继承B,其中B是被继承者称之为父类或者超类,D是继承者称之为子类或者派生类。

构造器

说到继承就必须讲一下构造器了,子类继承父类的属性和方法,除了那些private修饰的属性和方法,构造器也是子类继承不了的。对于构造器而言,只能通过super( )调用,不能被继承。

我们是用super是按对父类的构造器的调用,使用super调用构造器必须是父类构造器的第一条语句。如果子类的构造就没有显示地调用父类的构造器,则自动调用父类没有参数的构造器。如果父类没有不带参数的构造器,在子类中又没有显式的调用超类的其他构造器,则会报错。


public class Person {
    protected String name;
    protected int age;
    protected String sex;
    
    Person(){
        System.out.println("Person Constrctor...");
    }
}

public class Husband extends Person{
    private Wife wife;

    Husband(){
        System.out.println("Husband Constructor...");
    }
    
    public static void main(String[] args) {
        Husband husband  = new Husband();
    }
}  复制代码

输出

Person Constrctor...
Husband Constructor...复制代码

通过这个示例可以看出,构建过程是从父类向外扩散的,也就是从父类开始向子类一级一级地完成构建。

但是,这个默认调用父类的构造器是有前提的:父类有默认构造器。如果父类没有默认构造器,我们就要必须显示的使用super()来调用父类构造器,否则编译器会报错:无法找到符合父类形式的构造器。

public class Person {
    protected String name;
    protected int age;
    protected String sex;
    
    Person(String name){
        System.out.println("Person Constrctor-----" + name);
    }
}

public class Husband extends Person{
    private Wife wife;

    Husband(){
        super("chenssy");
        System.out.println("Husband Constructor...");
    }
    
    public static void main(String[] args) {
        Husband husband  = new Husband();
    }
}复制代码

输出

Person Constrctor-----chenssy
Husband Constructor...复制代码

上面的例子就是,子类会默认调用父类的构造器,因为父类没有默认的父类构造器,子类必须要显示的指定父类的构造器

多重继承

多重继承指的的是一个类可以同时从多个父类哪里机会才能行为和特征,然而我们知道Java为了保证数据安全,它只能允许单继承。但是我Java提供了两种方式让我们曲折来实现多重继承:接口和内部类。

接口

在介绍接口和抽象类的时候了解到子类只能继承一个父类,也就是说只能存在单一继承,但是却可以实现多个接口,这就为我们实现剁成继承做了铺垫。

对于接口,接口是没有任何具体实现的,也就是说,没有任何域接口相关的存储。

interface CanFight {
    void fight();
}

interface CanSwim {
    void swim();
}


interface CanFly {
    void fly();
}

public class ActionCharacter {
    public void fight(){
        
    }
}

public class Hero extends ActionCharacter implements CanFight,CanFly,CanSwim{

    public void fly() {
    }

    public void swim() {
    }

    /**
     * 对于fight()方法,继承父类的,所以不需要显示声明
     */
}复制代码


内部类

关于内部类,我在关于封装的内容里已经介绍过了,大家可以点进去看一下。


关注下面的标签,发现更多相似文章
评论