java继承(extends关键字)

引入:众所周知,继承性是面向对象的第二大特征。

看下面两代码:一个Person类,一个Student类。

Person类:

class Person{
    private String name;
    private String sex;
    private int age;
    //省略getter、setter方法
}

Student类:

class Student {
    private String name;
    private String sex;
    private String school;
    private int age;
    //省略getter、setter方法
}

经过比较,看看呀很清楚的发现,以上两个类中存在了不少重复。而继承就是解决这个问题来的。

一、继承的概念

继承是面向对象的一个显著的特征。继承是从已有的类中派生出新类,新的类能吸收已有类的属性和方法,并能扩展新的属性和方法。

继承的语法格式:

class 子类 extends 父类{}

子类也被称为派生类,父类有被称为基类、超类

范例(继承的实现):
 

package com.wfg.demo;

/**
 * @Author WFG
 * @Date 2019/6/1 19:45
 */
class Person{
    private String name;
    private String sex;
    private int age;

    public String getName() {
        return name;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
class Student extends Person {

}

public class TestDemo {
    public static void main(String[]args){
        Student stu1 = new Student();//实例化的是子类
        stu1.setName("王富贵");//调用的是父类方法
        stu1.setSex("你猜啊");//调用的是父类方法
        stu1.setAge(18);//调用的是父类的方法
        System.out.println("姓名:"+stu1.getName()
                +",性别:"+stu1.getSex()+",年龄:"+stu1.getAge());
    }
}

运行结果:
 

姓名:王富贵,性别:你猜啊,年龄:18

分析以上代码以及结果:
子类(Student)并没有定义任何的操作,而在主类中所使用的全部是由父类(Person类)定义的,这也就说明了,子类即使不扩充父类,也能维持父类的操作。

范例2(在子类中扩充父类的功能):
 

package com.wfg.demo;

/**
 * @Author WFG
 * @Date 2019/6/1 19:45
 */
class Person{
    private String name;
    private String sex;
    private int age;

    public String getName() {
        return name;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
class Student extends Person {
    private String school;

    public String getSchool() {
        return school;
    }

    public void setSchool(String school) {
        this.school = school;
    }
}

public class TestDemo {
    public static void main(String[]args){
        Student stu1 = new Student();//实例化的是子类
        stu1.setName("王富贵");//调用的是父类方法
        stu1.setSex("你猜啊");//调用的是父类方法
        stu1.setAge(18);//调用的是父类的方法
        stu1.setSchool("某某大学");//子类自己的方法
        System.out.println("姓名:"+stu1.getName()
                +",性别:"+stu1.getSex()+",年龄:"+stu1.getAge()
                +",学校:"+stu1.getSchool());
    }
}

运行结果:
 

姓名:王富贵,性别:你猜啊,年龄:18,学校:某某大学

以上代码,子类对于父类的功能进行了扩充(扩充了一个属性和两个方法),从表面上看,子类扩充了父类的功能,但是子类还有一个特点:子类实际上是将父类的定义更加具体化了,父类表示的范围大,而子类表示的范围小。

二、继承的限制

虽然继承可以进行功能的扩充,但是其在定义的时候也是有若干限制的:

2.1限制一:一个子类只能继承一个父类(单继承局限)

范例(继承多个的错误写法):

class A{}
class B{}
class C extends A,B{}

这种操作称为多重继承,实际上以上的做法无非就是希望一个子类可以继承多个父类的功能,但以上的语法不支持,可以换为以下的写法:

class A{}
class B extends A{}
class C extends B{}

在这里,C实际上属于(孙)子类,这样一来,相当于B继承了A的全部方法,而C又继承了A和B的方法,这种操作称为多层继承。

2.2限制:二:在一个子类继承的时候,实际上会继承父类中所有的属性和方法,但是要注意的是,对于所有的非私有操作(没有private)属于显示继承(可以直接利用对象操作),而所有的私有操作属于隐式继承(间接完成)。

范例:
 

package com.wfg.demo;

import javax.naming.Name;

/**
 * @Author WFG
 * @Date 2019/6/1 20:28
 */

class A {
    private String name;

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

    public String getName() {
        return name;
    }
}

class B extends A{
    public void print() {
        //错误,name属性是私有的(被private修饰),对外不可见
        System.out.println(name);
    }
}
public class TestDemo3 {
    public static void main(String[]args){
        B b = new B();
        b.setName("王富贵");
        System.out.println(b.getName());
    }
}

虽然对A类中的name属性无法直接进行访问,但是却可以通过getter、setter方法间接的进行操作。

2.3限制三:在继承关系中,如果要实例化子类的对象,会默认的先调用父类的构造,为父类之中的属性初始化,之后再调用子类构造,为子类之中的属性初始化,即:默认情况下,子类会找到父类之中的无参构造方法。

package com.wfg.demo;

import javax.naming.Name;

/**
 * @Author WFG
 * @Date 2019/6/1 20:28
 */

class A {
    public A() {
        System.out.println("这是父类的无参构造");
    }
}
class B extends A {
    public B() {
        System.out.println("这是子类的构造");
    }
}
public class TestDemo3 {
    public static void main(String[]args){
        B b = new B();//实例化子类的对象
    }
}

运行结果:

这是父类的无参构造
这是子类的构造

虽然实例化的是子类的对象,但是从上我们可以看出,它会默认先执行父类的构造,调用父类构造方法执行,而后在实例化子类的对象,调用子类的构造方法,这个时候,对于子类而言,相当于隐含了一个super()的形式:

class B extends A {
    public B() {
        super();//调用父类的构造
        System.out.println("这是子类的构造");
    }
}

以上例子都是调用的父类的无参构造,而如果这时候父类没有无参构造,则子类必须通过super()调用指定参数的构造方法:
 

package com.wfg.demo;

import javax.naming.Name;

/**
 * @Author WFG
 * @Date 2019/6/1 20:28
 */

class A {
    public A(String name) {
        System.out.println("这是父类的有参构造");
    }
}
class B extends A {
    public B() {
        super("王富贵");//调用父类的构造
        System.out.println("这是子类的构造");
    }
}
public class TestDemo3 {
    public static void main(String[]args){
        B b = new B();//实例化子类的对象
    }
}

运行结果:

这是父类的有参构造
这是子类的构造

在任何情况下,子类都逃不出父类的构造方法的调用,很明显,super调用父类构造,这个语法和this很相似:super调用父类构造时,一定要放在构造方法的首行。(this关键字:this关键字作用

 

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值