java中的继承

1、为什么要有继承

代码中创建的类,主要是为了抽象现实中的一些事物(包含属性和方法)
有的时候客观事物之间就存在一些关联关系,那么在表示成类和对象的时候也会存在一定的关联
例如, 设计一个类表示动物:

// Animal.java
public class Animal {
  public String name;

  public Animal(String name) {
    this.name = name;
  }

  public void eat(String food) {
    System.out.println(this.name + "正在吃" + food);
  }
}

// Cat.java
class Cat {
  public String name;

  public Cat(String name) {
    this.name = name;
  }

  public void eat(String food) {
    System.out.println(this.name + "正在吃" + food);
  }
}

// Bird.java
class Bird {
  public String name;

  public Bird(String name) {
    this.name = name;
  }

  public void eat(String food) {
    System.out.println(this.name + "正在吃" + food);
  }

  public void fly() {
    System.out.println(this.name + "正在飞 ︿( ̄︶ ̄)︿");
  }
}

这个代码我们发现其中存在了大量的冗余代码
仔细分析,我们发现 Animal 和 Cat 以及 Bird 这几个类中存在一定的关联关系

  • 这三个类都具备一个相同的 eat 方法,而且行为是完全一样的
  • 这三个类都具备一个相同的 name 属性,而且意义是完全一样的
  • 从逻辑上讲,Cat 和 Bird 都是一种 Animal (is - a 语义)

此时我们就可以让 Cat 和 Bird 分别继承 Animal 类,来达到代码重用的效果
此时,Animal 这样被继承的类,我们称为 父类 、基类 或 超类,对于像 Cat 和 Bird 这样的类,我们称为 子类,派生类和现实中的儿子继承父亲的财产类似,子类也会继承父类的字段和方法,以达到代码重用的效果

2、继承的语法规则及细节

基本语法

class 子类 extends 父类 {
}

  1. Java当中是单继承,不能同时继承两个类及其以上的类。(C++支持多继承)
  2. 子类构造的同时,先要帮助父类进行构造。
class Animal {
  public String name;
  public int age;
  public Animal(String name, int age) {
    this.name = name;
    this.age = age;
  }
}

class Cat extends Animal {
  public Cat(String name) {
    // 使用 super 显示的调用父类带有两个参数的的构造方法
    super(name);
  }
}

如果父类没有写构造函数,则子类也无序显示的调用父类的构造函数,例如:

class Animal {
  public String name;
  public int age;
}

class Cat extends Animal {
}

因为父类会隐式的生成一个无参的构造函数,而子类会隐式的调用父类的构造函数。

注意:super调用父类的构造方法时,只能放在第一行,否则会报错

在这里插入图片描述

继承的内存图:

在这里插入图片描述

在这里插入图片描述

当子类和父类中有同名的字段,优先使用子类的,如果想要使用父类字段,则需要使用super关键字,例如:

没有使用super:
在这里插入图片描述
使用super:
在这里插入图片描述

3、protected 关键字

如果把字段设为 private,子类不能访问。但是设成 public,又违背了我们 “封装” 的初衷
所以应该使用protected关键字

  • 对于类的调用者来说, protected 修饰的字段和方法是不能访问的
  • 对于类的子类和同一个包的其他类来说,protected 修饰的字段和方法是可以访问的

在父类中使用private:

class Animal {
  public String name;
  public int age;
  private String sex;
  public Animal(String name, int age) {
    this.name = name;
    this.age = age;
  }
}

class Bird extends Animal {
  String wing;
  String name;
  public Bird(String name, int age, String wing) {
    super(name, age);
    this.wing = wing;
  }
  public void fly() {
    System.out.println(super.name + wing);
  }

  public void PrintSex() {
    System.out.println(super.sex);
  }
}

在这里插入图片描述

在父类中使用protected:
在这里插入图片描述
在这里插入图片描述

Java 中对于字段和方法共有四种访问权限

  1. private: 类内部能访问, 类外部不能访问
  2. 默认(也叫包访问权限): 类内部能访问, 同一个包中的类可以访问, 其他类不能访问.
  3. protected: 类内部能访问, 子类和同一个包中的类可以访问, 其他类不能访问.
  4. public : 类内部和类的调用者都能访问

在这里插入图片描述

4、更复杂的继承关系

在生或中,类与类之前可能存在非常复杂的关系,例如:
在这里插入图片描述
这个时候使用继承方式来表示,就会涉及到更复杂的体系

// Animal.java 
public Animal { 
 ... 
} 
// Cat.java 
public Cat extends Animal { 
 ... 
} 
// ChineseGardenCat.java 
public ChineseGardenCat extends Cat { 
 ... 
} 
// OrangeCat.java 
public Orange extends ChineseGardenCat { 
 ... 
} 
......

如刚才这样的继承方式称为多层继承,即子类还可以进一步的再派生出新的子类

时刻牢记,我们写的类是现实事物的抽象。而我们真正在公司中所遇到的项目往往业务比较复杂,可能会涉及到一系列复杂的概念,都需要我们使用代码来表示, 所以我们真实项目中所写的类也会有很多。 类之间的关系也会更加复杂。

但是即使如此,我们并不希望类之间的继承层次太复杂。一般我们不希望出现超过三层的继承关系。如果继承层次太多,就需要考虑对代码进行重构了。

如果想从语法上进行限制继承,就可以使用 final 关键字

5、final关键字

final 关键字, 修饰一个变量或者字段的时候, 表示 常量 (不能修改)

final 关键字也能修饰类,此时表示被修饰的类就不能被继承

在这里插入图片描述

final 关键字的功能是限制类被继承

“限制” 这件事情意味着 “不灵活”。在编程中,灵活往往不见得是一件好事。灵活可能意味着更容易出错
使用 final 修饰的类被继承的时候,就会编译报错,此时就可以提示我们这样的继承是有悖这个类设计的初衷的

平时使用的 String 字符串类,就是用 final 修饰的,不能被继承
在这里插入图片描述

6、组合

和继承类似,组合也是一种表达类之间关系的方式,也是能够达到代码重用的效果
例如表示一个学校:

public class Student { 
 ... 
} 
public class Teacher { 
 ... 
} 
public class School { 
 public Student[] students; 
 public Teacher[] teachers; 
}

组合并没有涉及到特殊的语法(诸如 extends 这样的关键字),仅仅是将一个类的实例作为另外一个类的字段。这是我们设计类的一种常用方式之一。

组合表示 has - a 语义
在刚才的例子中,我们可以理解成一个学校中 “包含” 若干学生和教师

继承表示 is - a 语义
在上面的 “动物和猫” 的例子中,我们可以理解成一只猫也 “是” 一种动物

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值