继承(inheritance)是面向对象编程的核心机制之一,没有使用继承的程序设计,就不能成为面向对象的程序设计。继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。
继承的语法结构:
[修饰符列表] class 子类名 extends 父类名{
类体;
}
(1)子类就是当前这个类,父类就是我们要复用的那个类
(2)在java中,只允许单继承,也就是说 一个类最多只能显示地继承于一个父类。但是一个类却可以被多个类继承,也就是说一个类可以拥有多个子类。c++支持多继承
(3)一个类如果没有显式继承其他类,则该类默认继承Object
(4)任何一个类都有一个始祖类Object,所有类的超类。
代码示例如下:
//Person父类
public class Person{
String name;
int age;
void eat(String s){
System.out.println(s);
}
void sleep(String s){
System.out.println(s);
}
}
//Teacher子类
public class Teacher extends Person{
int salary;
String school;
void teach(String s){
System.out.println(s);
}
public static void main(String[] args){
Teacher t = new Teacher();
t.name = "张三"; //实例化Teacher 类对象t
System.out.println("教师"+t.name);
t.eat("吃"); //使用从父类继承来的成员方法eat()
t.sleep("睡"); //使用从父类继承来的成员方法sleep()
t.teach("上课"); //使用在Teacher类中定义的teach()方法
}
}
子类继承父类的成员变量
当子类继承了某个类之后,便可以使用父类中的成员变量,但是并不是完全继承父类的所有成员变量。具体的原则如下:
1)能够继承父类的public和protected成员变量;不能够继承父类的private成员变量;
2)对于父类的包访问权限成员变量,如果子类和父类在同一个包下,则子类能够继承;否则,子类不能够继承;
3)对于子类可以继承的父类成员变量,如果在子类中出现了同名称的成员变量,则会发生隐藏现象,即子类的成员变量会屏蔽掉父类的同名成员变量。如果要在子类中访问父类中同名成员变量,需要使用super关键字来进行引用。
子类继承父类的方法
同样地,子类也并不是完全继承父类的所有方法。
1)能够继承父类的public和protected成员方法;不能够继承父类的private成员方法;
2)对于父类的包访问权限成员方法,如果子类和父类在同一个包下,则子类能够继承;否则,子类不能够继承;
3)对于子类可以继承的父类成员方法,如果在子类中出现了同名称的成员方法,则称为覆盖,即子类的成员方法会覆盖掉父类的同名成员方法。如果要在子类中访问父类中同名成员方法,需要使用super关键字来进行引用。
注意:隐藏和覆盖是不同的。隐藏是针对成员变量和静态方法的,而覆盖是针对普通方法的。
有关构造器
子类是不能够继承父类的构造器,但是要注意的是,如果父类的构造器都是带有参数的,则必须在子类的构造器中显示地通过super关键字调用父类的构造器并配以适当的参数列表。如果父类有无参构造器,则在子类的构造器中用super关键字调用父类构造器不是必须的,如果没有使用super关键字,系统会自动调用父类的无参构造器。
super关键字的使用
1 用于从派生类访问基类的成员
2 派生类要调用基类的构造方法 super(),super()只能在派生类的构造方法中调用,位于方法首行。
3 调用基类已被其他方法重写的方法
4 访问基类的数据成员:super.成员变量、super.成员方法
为什么要继承?
代码的复用,方法的重写、覆盖。
在有继承关系的两个类中:
private(私有)可以被继承,但无法访问和覆盖,即使在子类中覆盖了父类的方法,在多态里面仍然会调用父类的方法。
静态方法有继承无覆盖,覆盖发生在对象的成员方法中,也就是发生在堆内存中,但是静态数据都是在静态内存块中。
发生覆盖的条件:
1 发生在有继承关系的两个类之间
2 方法必须具有相同的方法名,返回值类型,参数列表(如果参数列表不同,系统会默认这两个重载后的不同的两个方法)
3 重写的方法不能比被重写的方法有更低的访问权限
4 重写的方法不能比被重写的方法抛出更宽泛的异常
5 私有方法不能被覆盖,不调用不报错,调用就报错
6 构造方法无法被覆盖,因为构造方法不能被继承
7 静态方法不存在覆盖,继承是对象的继承,而不是类的继承。静态方法进入内存以后,不会再有新的内存变化,所以没有覆盖这一说。
8 覆盖指的是成员方法,和成员变量无关。