Java 继承
继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。继承可以理解为一个对象从另一个对象获取属性的过程。
如果类A是类B的父类,而类B是类C的父类,我们也称C是A的子类,类C是从类A继承而来的。在Java中,类的继承是单一继承,也就是说,一个子类只能拥有一个父类
继承中最常使用的两个关键字是extends和implements。
这两个关键字的使用决定了一个对象和另一个对象是否是IS-A(是一个)关系。
通过使用这两个关键字,我们能实现一个对象获取另一个对象的属性。
所有Java的类均是由java.lang.Object类继承而来的,所以Object是所有类的祖先类,而除了Object外,所有类必须有一个父类。
如果类A是类B的父类,而类B是类C的父类,我们也称C是A的子类,类C是从类A继承而来的。在Java中,类的继承是单一继承,也就是说,一个子类只能拥有一个父类
继承中最常使用的两个关键字是extends和implements。
这两个关键字的使用决定了一个对象和另一个对象是否是IS-A(是一个)关系。
通过使用这两个关键字,我们能实现一个对象获取另一个对象的属性。
所有Java的类均是由java.lang.Object类继承而来的,所以Object是所有类的祖先类,而除了Object外,所有类必须有一个父类。
1、extends
通过过extends关键字可以申明一个类是继承另外一个类而来的,一般形式如下:// A.java
public class A {
private int i;
protected int j;
public void func() {
}
}
// B.java
public class B extends A {
}
小结:以上的代码片段说明,B由A继承而来的,B是A的子类。而A是Object的子类,这里可以不显示地声明。
作为子类,B的实例拥有A所有的成员变量,但对于private的成员变量B却没有访问权限,这保障了A的封装性。
作为子类,B的实例拥有A所有的成员变量,但对于private的成员变量B却没有访问权限,这保障了A的封装性。
IS-A关系
IS-A就是说:一个对象是另一个对象的一个分类。
下面是使用关键字extends实现继承。
下面是使用关键字extends实现继承。
public class Animal{
}
public class Mammal extends Animal{
}
public class Reptile extends Animal{
}
public class Dog extends Mammal{
}
基于上面的例子,以下说法是正确的:
--Animal类是Mammal类的父类。
--Animal类是Reptile类的父类。
--Mammal类和Reptile类是Animal类的子类。
--Dog类既是Mammal类的子类又是Animal类的子类。
分析以上示例中的IS-A关系,如下:
--Mammal IS-A Animal
--Reptile IS-A Animal
--Dog IS-A Mammal
因此 : Dog IS-A Animal
通过使用关键字extends,子类可以继承父类所有的方法和属性,但是无法使用 private(私有) 的方法和属性。
我们通过使用instanceof 操作符,能够确定Mammal IS-A Animal
2、Implements
Implements关键字使用在类继承接口的情况下, 这种情况不能使用关键字extends。
实例:
public interface Animal {}
public class Mammal implements Animal{
}
public class Dog extends Mammal{
}
3、instanceof 关键字
可以使用 instanceof 运算符来检验Mammal和dog对象是否是Animal类的一个实例。
<pre name="code" class="java">interface Animal{}
class Mammal implements Animal{}
public class Dog extends Mammal{
public static void main(String args[]){
Mammal m = new Mammal();
Dog d = new Dog();
System.out.println(m instanceof Animal);
System.out.println(d instanceof Mammal);
System.out.println(d instanceof Animal);
}
}
编译结果:
true
true
true
4、下面介绍一些继承的应用:
一、子类可以继承父类所有public的方法和属性:class Person {
private int age;
public void setAge(int age) {
if (age < 0 || age > 200)
age = 0;
else {
this.age = age;
}
}
public int getAge() {
return age;
}
}
class Student extends Person{
}
public class Ext {
public static void main (String args[]) {
Student stu = new Student();
stu.setAge(10);
System.out.println(stu.getAge());
}
}
编译运行:
10
class Person {
private int age;
public void setAge(int age) {
if (age < 0 || age > 200)
age = 0;
else {
this.age = age;
}
}
public int getAge() {
return age;
}
}
class Student extends Person{
private String school;
public void setSchool(String school) {
this.school = school;
}
public String getSchool() {
return school;
}
public Student(String school) {
this.school = school;
}
}
public class Ext2 {
public static void main (String args[]) {
Student stu = new Student("ustc");
stu.setAge(10);
System.out.println(stu.getAge());
System.out.println(stu.getSchool());
}
}
运行结果:
10
ustc
分析:
Student stu = new Student("ustc"); //执行Student类的构造函数,this.school = ustc;
stu.setAge(10);//执行Person类的setAge,this.age = age;
System.out.println(stu.getAge());//执行setAge输出10;
System.out.println(stu.getSchool());//执行构造函数,输出ustc
System.out.println(stu.getAge());//执行setAge输出10;
System.out.println(stu.getSchool());//执行构造函数,输出ustc
三、看个例子:
class Person {
private int age;
public void setAge(int age) {
if (age < 0 || age > 200)
age = 0;
else {
this.age = age;
}
}
public int getAge() {
return age;
}
public void printInfo() {
System.out.println("age = "+age);
}
}
class Student extends Person{
private String school;
public void setSchool(String school) {
this.school = school;
}
public String getSchool() {
return school;
}
public Student(String school) {
this.school = school;
}
/* override */
public void printInfo() {
System.out.println("school = "+school+"; age = "+getAge());
}
}
public class Ext3 {
public static void main (String args[]) {
Student stu = new Student("ustc");
stu.setAge(10);
System.out.println(stu.getAge());
System.out.println(stu.getSchool());
stu.printInfo();
}
}
运行结果:
10
ustc
school = ustc; age = 10
分析:
看最后一句stu.printInfo()程序输出是school = ustc; age = 10,这就说明Student继承Person并且重写了printInfo方法,最后调用的是重写后的方法。
四、还是先看一个例子
四、还是先看一个例子
class Person {
private int age;
public void setAge(int age) {
if (age < 0 || age > 200)
age = 0;
else {
this.age = age;
}
}
public int getAge() {
return age;
}
public void printInfo() {
System.out.println("age = "+age);
}
public Person () {System.out.println("Person ()");}
public Person (int age) {
System.out.println("Person (int age)");
this.age = age;
}
}
class Student extends Person{
private String school;
public void setSchool(String school) {
this.school = school;
}
public String getSchool() {
return school;
}
public Student(String school) {
/* will call the super() */
//super();
super(5);
System.out.println("Student(String school)");
this.school = school;
}
/* override */
public void printInfo() {
System.out.println("school = "+school+"; age = "+getAge());
}
}
public class Ext4 {
public static void main (String args[]) {
Student stu = new Student("ustc");
//stu.setAge(10);
System.out.println(stu.getAge());
System.out.println(stu.getSchool());
stu.printInfo();
}
}
运行结果:
Person (int age)
Student(String school)
5
ustc
school = ustc; age = 5
分析:
Student stu = new Student("ustc");//首先调用两个类的构造方法,但是调用的顺序是怎么样的呢?super(5)的作用先执行父类的构造方法,即先输出Person (int age),再输出Student(String school);
System.out.println(stu.getAge());//由于上面super(5)传入了5,所以输出5,然后输出ustc;
stu.printInfo();//上同
补充:super关键字的使用
super调用超类的构造器
--使用 super调用构造器的语句必须是子类构造器的第一条语句。
--如果子类的构造器没有显式地(根据传入的参数而定调用哪个构造函数)调用超类的构造器,则将自动调用超类的默认(没有参数)的构造器。
--使用 super调用构造器的语句必须是子类构造器的第一条语句。
--如果子类的构造器没有显式地(根据传入的参数而定调用哪个构造函数)调用超类的构造器,则将自动调用超类的默认(没有参数)的构造器。
五、例子
abstract class Father {
private int money;
public int getMoney() {return money; }
public void setMoney(int money) {this.money = money; }
public abstract void study();
}
interface A {
public static final int i = 10;
public abstract int getNum();
}
interface B {
public static String name = "InterfaceB";
public abstract String getName();
}
class Son extends Father implements A,B{
public int getNum() {return i;}
public String getName() {return name;}
public void study() {System.out.println("I am study"); }
}
public class Ext7 {
public static void main (String args[]) {
Son son = new Son();
System.out.println(son.getName());
son.study();
}
}
运行结果:
InterfaceB
I am study
分析:
继承实现了A、B接口,重写了接口的方法。