java基础之继承

java基础之继承

一、定义

就如上一篇文章所属,在二维平面中所有的图形都可以抽象为形状。对于这个抽象也有自己基本的属性,每一种图形都有自己面积周长的计算方式。可以把共有的属性提取出来放在一个类中,在这里我们称之为基类父类。后面有其他的二维图形如三角形正方形等,只要使用关键字extends即可复用我们抽象出来的方法,通过这个关键字产生的类称之为子类。上述方式称之为继承。所以继承表述的是一种is-a的关系,A是B的一种,那么可以表示为A继承与B。

二、继承初始化顺序
public class Shape {
    private Float circumference;
    private Float square;

    public Shape(){
        System.out.println("基类初始化");
    }
}

public class EquilateralTriangle extends Shape{
    private Float length;
    private Float height;

    public EquilateralTriangle(){
       System.out.println("子类初始化");
    }
}
//输出结果
基类初始化
子类初始化

从代码的结构可以看出,在子类初始化的时候假如基类存在无参数的构造函数,子类的构造函数将会隐式的调用基类的无参数构造。在Java中不指定构造函数,会有默认的无参数构造函数。但是在基类中指定了构造函数,则需要使用super关键字对基类进行初始化。

三、protected关键字

在上述的案例中,一个图形的周长和面积是根据具体的图形以及其自己计算方式计算出来,但是这两个值的计算只有在形状被确定下来之后,计算才会有意义。所以需要在子类中调用set方法设置对应的值,但是又不希望被其他的类调用。在这里就需要使用到protected关键字。protected关键字访问权限是同包或者子类可以访问,在其他包中的其他类是不可以被访问。

public class Shape {
    private Float circumference;
    private Float square;

    public Shape(){
      
    }
    public Float getSquare() {
        return square;
    }
    public Float getCircumference() {
        return circumference;
    }

    protected void setCircumference(Float circumference){
        this.circumference = circumference;
    }

    protected void setSquare(Float square){
        this.square = square;
    }
}
public class EquilateralTriangle extends Shape{
    private Float length;
    private Float height;

    public EquilateralTriangle(Float length, Float height){
        if (length > 0 && height > 0){
            this.height = height;
            this.length = length;
            Float circumference = length*3;
            setCircumference(circumference);
            Float square = length*height/2;
            setSquare(square);
        }
    }

    @Override
    public Float getCircumference() {
        return super.getCircumference();
    }

    @Override
    public Float getSquare() {
        return super.getSquare();
    }

    public void setLength(Float length) {
        this.length = length;
        Float circumference = length*3;
        setCircumference(circumference);
        Float square = length*height/2;
        setSquare(square);
    }

    public void setHeight(Float height) {
        this.height = height;
        Float circumference = length*3;
        setCircumference(circumference);
        Float square = length*height/2;
        setSquare(square);
    }
      public static void main(String[] args) {
        EquilateralTriangle equilateralTriangle = new EquilateralTriangle(1F,2F);
        System.out.println(equilateralTriangle.getCircumference());
        System.out.println(equilateralTriangle.getSquare());
    }
}
//输出结果
3.0
1.0
四、继承优点以及缺点
  1. 优点
    • 代码复用,可以较少重复代码。
  2. 缺点
    • 继承层次过深,会导致代码结构复杂,耦合性强。
    • 基类的修改会直接影响到子类。
五、向上转型

在上面我们谈到is-a的关系,等边三角形是一种平面图形。我们可以说等边三角形是一种图形但是不能说图形就是等边三角形。如下

public class Shape {
    private Float circumference;
    private Float square;

   // get set等各种方法
  
    public Shape(){
        System.out.println("基类初始化");
    }
    static void printSquare(Shape shape){
        System.out.println(shape.getSquare());
    }
}

public class EquilateralTriangle extends Shape{
    private Float length;
    private Float height;
  
    // get set等各种方法
    public static void main(String[] args) {
        EquilateralTriangle equilateralTriangle = new EquilateralTriangle(1F,2F);
        Shape.printSquare(equilateralTriangle);
    }
}


通过Shape.printSquare(equilateralTriangle),可以看出equilateralTriangleShape类型。

将子类转换成父类,在继承关系上面是向上移动的,所以一般称之为向上转型。由于向上转型是从一个叫专用类型向较通用类型转换,所以它总是安全的,唯一发生变化的可能就是属性和方法的丢失。这就是为什么编译器在未曾明确表示转型未曾指定特殊标记的情况下,仍然允许向上转型的原因。

六、继承的使用场景

Java编程思想中有句话可作为判断是否使用继承一句:问一问自己是否需要从子类向父类进行向上转型。如果必须向上转型,则继承是必要的,但是如果不需要,则应当好好考虑自己是否需要继承。

参考资料

参考资料

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值