目录
1.继承的作用
2.继承树
3.protected和super
protected
super
注:super/this()--构造方法,第一行,一般不同时出现
4.向上向下转型
向上转型
向下转型
final
小结
1.继承的作用
理解:首先就是可以实现代码复用,比如当我们让Student继承Person时, Student 就获得了Person的所有功能。只需要给Student编写新的功能(关键字extends)。
代码部分如下:
class Person {private String name;private int age;public String getName() {...}public void setName(String name) {...}public int getAge() {...}public void setAge(int age) {...}
}class Student extends Person {// 不要重复name和age字段/方法,// 只需要定义新增score字段/方法:private int score;public int getScore() { … }public void setScore(int score) { … }
}
注意:
OOP术语中我们把Person称为 超类(super class),父类(parent class),基类(base class, Student称为子类(sub class).
2.继承树
一般来说,java中,父类没有明确写继承的类,编译器会自动加上extends object,所有的类最终的都会指向Object(Object没有父类)。一个简单的继承树如下图所示:
┌───────────┐
│ Object │
└───────────┘▲│
┌───────────┐
│ Person │
└───────────┘▲│
┌───────────┐
│ Student │
└───────────┘如果在定义一个Teacher类继承Person类,继承树如下:┌───────────┐│ Object │└───────────┘▲│┌───────────┐│ Person │└───────────┘▲ ▲│ ││ │
┌───────────┐ ┌───────────┐
│ Student │ │ Teacher │
└───────────┘ └───────────┘
3.protected和super
protected
理解(protect): 由于继承就是子类无法访问父类的private
字段或者private
方法,
为了让子类可以访问父类的字段,我们需要把private
改为protected
。用protected
修饰的字段可以被子类访问:
class Person {protected String name;protected int age;
}class Student extends Person {public String hello() {return "Hello, " + name; // OK!}
}
protected
关键字可以把字段和方法的访问权限控制在继承树内部,一个protected
字段和方法可以被其子类,以及子类的子类所访问:
class Person {protected String name;protected int age;
}class Student extends Person {public String hello() {return "Hello, " + name; // OK!}
}
super
super
关键字表示父类(超类)。子类引用父类的字段时,可以用super.fieldName。
class Student extends Person {public String hello() {return "Hello, " + super.name;}
}
public class Main {public static void main(String[] args) {Student s = new Student("Xiao Ming", 12, 89);}
}class Person {protected String name;protected int age;public Person(String name, int age) {this.name = name;this.age = age;}
}class Student extends Person {protected int score;public Student(String name, int age, int score) {this.score = score;}
}
在Java
中,任何class
的构造方法,第一行语句必须是调用父类的构造方法。如果没有明确地调用父类的构造方法,编译器会帮我们自动加一句super()。
class Student extends Person {protected int score;public Student(String name, int age, int score) {super(); // 自动调用父类的构造方法this.score = score;}
}
注:super/this()--构造方法,第一行,一般不同时出现
4.向上向下转型
向上转型
Student s = new Student();
Person p = new Person();
// 引用类型为Person的变量指向Student类型的实例
Person p = new Student();
Student
继承自Person
,因此,它拥有Person
的全部功能。Person
类型的变量,如果指向Student
类型的实例,对它进行操作,是没有问题的。这种把一个子类类型安全地变为父类类型的赋值,被称为向上转型(upcasting
)。
注:可以把Student类型转型为Person,或者更高层次的Object。
向下转型
和向上转型相反,如果把一个父类类型强制转型为子类类型,就是向下转型(downcasting
)
Person p1 = new Student(); // upcasting, ok
Person p2 = new Person();
Student s1 = (Student) p1; // ok
Student s2 = (Student) p2; // runtime error! ClassCastException!
运行时,Person
类型p1
实际指向Student
实例,Person
类型变量p2
实际指向Person
实例。在向下转型的时候,把p1
转型为Student
会成功,因为p1
确实指向Student
实例,把p2
转型为Student
会失败,由于p2
的实际类型是Person
,不能把父类变为子类,因为子类功能比父类多,多出的功能无法凭空变出来。因此,向下转型很可能会失败。失败的时候,Java虚拟机会报ClassCastException
异常。
为了避免向下转型出错,Java
提供了instanceof
操作符,可以先判断一个实例究竟是不是某种类型:
Person p = new Person();
System.out.println(p instanceof Person); // true
System.out.println(p instanceof Student); // falseStudent s = new Student();
System.out.println(s instanceof Person); // true
System.out.println(s instanceof Student); // trueStudent n = null;
System.out.println(n instanceof Student); // false
instanceof
实际上判断一个变量所指向的实例是否是指定类型,或者这个类型的子类。如果一个引用变量为null
,那么对任何instanceof
的判断都为false
。利用instanceof
,在向下转型前可以先判断:
Person p = new Student();
if (p instanceof Student) {// 只有判断成功才会向下转型:Student s = (Student) p; // 一定会成功
}
final
-
// 类被final修饰,表示此类不能有子类,public final class Fu{
-
// final 修饰符基本数据类型变量-- 常量值不可变
-
// final 修饰符引用数据类型变量-- 地址不可变
-
// 当final修饰方法,表示此方法不能被重写,但是final可被子类使用
小结
- 继承是面向对象编程的一种强大的代码复用方式
- Java只允许单继承,所有类最终的根类是
Object
- 子类可以访问访问父类的
public
和protected
字段和方法 - 子类的构造方法可以通过
super()
调用父类的构造方法 - 当父类中不存在无参构造方法时,子类必须手动的调用父类的有参构造方法,并且必须在子类构造方法中的第一行
- 可以安全地向上转型为更抽象的类型
- 向下转型,可以使用
instanceof
运算符:用于判断"引用指向的对象"是否是"指定类型",运算结果为boolean
类型 - 子类和父类的关系是
is
,has
关系不能用继承