笔记来自2019求知讲堂零基础Java入门编程视频教程 https://www.bilibili.com/video/av76235341
理解类的继承
假设我们需要写一个Student类、一个Teacher类、一个Worker类。类的属性和方法如下:
Student类{姓名、性别、年龄、学校、打印信息方法}
Teacher类{姓名、性别、年龄、科目、打印信息方法}
Worker类{姓名、性别、年龄、工种、打印信息方法}
现在如果要建立这三个类,会发现将存在大量重复的代码,包括姓名性别年龄等属性,以及打印信息的方法,这样会使程序十分冗杂。
所以java提供了继承来解决这个问题,继承的思想下,我们可以先建立一个Person类,类中存放这三个类中的公共的属性和方法,然后这三个类可以通过继承获得这些公共属性和方法,然后还可以定义自己的独有的属性和方法。
下面以一个简单的代码来理解
//Person类——父类
public class Person {
int age;
String name;
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void showInfo() {
System.out.println("年龄" + this.age);
System.out.println("姓名" + this.name);
}
}
//Student类——子类
public class Student extends Person{ //通过extends实现继承
String school; //定义Student独有的school属性
public void setSchool(String school) { //定义Student独有的setSchool方法
this.school = school;
}
public void showInfo() {
//年龄姓名属性没有定义,但因为继承关系,所以可以使用
System.out.println("年龄" + this.age);
System.out.println("姓名" + this.name);
System.out.println("学校" + this.school);
}
}
//Test类
public class Test {
public static void main(String[] args) {
Student stu = new Student();
//Student类也可以直接使用父类Person类中的setAge()和setName()方法
stu.setName("知晓");
stu.setAge(18);
stu.setSchool("工商");
stu.showInfo();
}
}
所以总结起来,当多个类中存在相同属性和行为时,将这些重复的内容抽取到单独的一个父类中,那么这些子类则无需再定义这些属性和行为,只要继承父类即可。
继承的规则
-
语法规则:
class Subclass extends Superclass{} -
子类继承父类,就继承了父类的所有方法和属性(除了父类的构造方法),子类中可以使用父类的方法属性,也可以创建新的方法和属性
-
Java中继承的关键字是extends,即子类不是父类的子集,而是对父类的扩展。
-
子类不能直接访问父类的中私有(private)的成员变量和方法(可以使用protected)。
-
Java只支持单继承,不允许多重继承,即一个子类只能有一个父类,一个父类可以有多个子类;但可以有多层继承,即A继承B,B继承C,这样是可以的。
注:
- 继承的出现提高了代码的复用性
- 继承的出现让类与类之间产生了关系,提供了多态的前提
- 不要仅为了获取其他类中的某个功能而去继承,继承过程要有逻辑关系(比如狗也有姓名性别年龄,但不能让Dog类直接继承Person类,正确的做法是创建Animal类,然后让Dog类去继承)
方法的重写(override)
在子类中可以根据需要对从父类继承来的方法进行改造,执行程序时,子类的方法将覆盖父类的方法。
上面的代码中,Student类中的showInfo()方法就是对Person类showInfo()方法的重写。
方法重写的要求
- 重写方法必须和被重写的方法具有相同的方法名称、参数列表。
- 重写方法不能使用比被重写方法更严格的权限。(比如父类方法是public的,子类重写的方法就不能是缺省、protected或private的)
- 子类方法抛出的异常不能大于被重写方法的异常。
- 子类的返回值类型不能大于被重写方法。(例如,父类方法返回值为Person,子类重写该方法的返回值可以是Student,但不能是Object)
- 重写和被重写的方法必须同时为static的,或者同时为非static的
例:圆柱继承圆,求圆柱体积
//Circle类
public class Circle {
public final static double PI = 3.14;
public double r;
public double getR() {
return r;
}
public void setR(double r) {
this.r = r;
}
public double getArea(double r) {
double area = PI * r * r;
return area;
}
}
//Cylinder类
public class Cylinder extends Circle{
double length;
public double getLength() {
return length;
}
public void setLength(double length) {
this.length = length;
}
public double findVolume() {
double volume = this.getArea(this.r) * this.length;
return volume;
}
}
//Test类
public class Test {
public static void main(String[] args) {
Cylinder cylinder = new Cylinder();
cylinder.setR(2);
cylinder.setLength(2);
double volume = cylinder.findVolume();
System.out.println(volume);
}
}
继承和组合
除了继承可以方便代码的复用,还有一种方式也可以方便的实现代码复用,那就是组合。
组合的核心是将父类对象作为子类的属性,然后子类通过调用这个属性来获得父类的属性和方法。
组合比继承更加灵活,如果一个类想使用另一个类的属性方法但有没有逻辑上的继承关系,就可以使用组合。
简单来说,继承用来处理“is-a”关系,组合用来处理“has-a”关系。
public class Person {
private int age;
private String name;
public Person() {
age = 18;
name = "知晓";
}
public void printInfo() {
System.out.print("年龄是:" + age);
System.out.println(" 姓名是:" + name);
}
//用两种方式调用Person类的printInfo()方法,效果相同
public static void main(String[] args) {
Teacher teacher = new Teacher();
teacher.person.printInfo();
Teacher2 teacher2 = new Teacher2();
teacher2.printInfo();
}
}
//Teacher类使用组合方式获得Person类的方法属性
class Teacher {
Person person = new Person();
}
//Teache2r类使用继承方式获得Person类的方法属性
class Teacher2 extends Person{
}