继承性是面向对象的第二大主要特征.
继承性即扩充一个类已有的功能.格式如下:
class 子类 extends 父类 {}
说明:
1.子类又被称为派生类;
2.父类又被称为超类(super class)
范例1:继承的基本实现
class Person{
private String name ;
private int age ;
public void setName(String name){
this.name = name ;
}
public void setAge(int age){
this.age = age ;
}
public String getName(){
return this.name ;
}
public int getAge(){
return this.age ;
}
}
class Student extends Person{ //Student类继承了Person类
}
public class Demo2{
public static void main(String args[]){
Student stu = new Student() ;
stu.setName("张三") ;
stu.setAge(12) ;
System.out.println("姓名:" + stu.getName() + ",年龄:" + stu.getAge()) ;
}
}
运行结果:
以上代码中,子类(Student类)没有定义任何操作,所有操作都是由Person类定义的,这说明子类及时不扩充父类也可以维持父类.
下面的代码演示子类对父类的功能进行扩充.范例2:
class Person{
private String name ;
private int age ;
public void setName(String name){
this.name = name ;
}
public void setAge(int age){
this.age = age ;
}
public String getName(){
return this.name ;
}
public int getAge(){
return this.age ;
}
}
class Student extends Person{ //Student类继承了Person类
private String school ;
public void setSchool(String school){
this.school = school ;
}
public String getSchool(){
return this.school ;
}
}
public class Demo2{
public static void main(String args[]){
Student stu = new Student() ;
stu.setName("张三") ;
stu.setAge(12) ;
stu.setSchool("清华大学") ;
System.out.println("姓名:" + stu.getName() + ",年龄:" + stu.getAge() + ",学校:" + stu.getSchool()) ;
}
}
运行结果:
在定义继承的时候会存在如下几条限制:
1.一个子类只能继承一个父类,存在单继承局限;
2.在一个子类继承时,会继承父类的所有操作(属性,方法),但是对于所有的非私有操作属于显式继承(可以直接利用对象操作),对于所有的私有操作属于隐式继承(需要间接完成)(见错例);
3.在继承关系中,如果要实例化子类对象,则过程为:先调用父类构造→为父类中的属性初始化→调用子类构造→为子类中的属性初始化.见范例3.
对于第一条限制,可以使用其他方式实现,如下:
class A{}
class B extends A{} //B类继承A类
class C extends C{} //C类继承B类,即C类继承了A类,B类的全部方法
java中
只允许多层继承(一般不超过3层),不允许多重继承.即java存在单继承局限.
错例:
class A{
private String msg ;
public void setMsg(String msg){
this.msg = msg ;
}
public String getMsg(){
return this.msg ;
}
}
class B extends A{
public void print(){
System.out.println(msg) ;
}
}
public class Demo{
public static void main(String args[]){
B b = new B() ;
b.setMsg("张三") ;
System.out.println(b.getMsg()) ;
}
}
编译结果:
由以上错误可以得出:A类中的msg这个私有属性无法进行直接访问,但是却可以通过setter,getter方法间接访问,并且也可以在B类的对象中保存msg属性的内容.即:私有属性页被继承下来,但无法直接使用.
范例3:
class A{
public A(){//父类无参构造
System.out.println("*********") ;
}
}
class B extends A{//子类构造
public B(){
System.out.println("#########") ;
}
}
public class Demo{
public static void main(String args[]){
B b = new B() ;
}
}
运行结果:
以上程序中,虽然实例化的是子类对象,但是发现他会默认先执行父类构造.此时,对于子类而言,就相当于隐含了一个super()的形式.范例4:
class A{
public A(){//父类无参构造
System.out.println("*********") ;
}
}
class B extends A{//子类构造
public B(){
super() ;
System.out.println("#########") ;
}
}
public class Demo{
public static void main(String args[]){
B b = new B() ;
}
}
运行结果:
在默认情况下,子类调用的是父类中的无参构造方法,而如果这个时候父类没有无参构造,则子类必须通过super()调用指定参数的构造方法.范例5:
class A{
public A(String msg){//父类无参构造
System.out.println("msg = " + msg) ;
}
}
class B extends A{//子类构造
public B(){
super("hello") ;
System.out.println("#########") ;
}
}
public class Demo{
public static void main(String args[]){
B b = new B() ;
}
}
运行结果:
在任何情况下,子类的实例化操作都会调用父类的构造方法,那么super调用父类构造时一定要放在构造方法的首行(所以this()和super()不会同时出现).
如果在一个类中有多个构造方法,并且之间使用this()互相调用的话,至少要保留一个构造方法作为出口,通过上例可知,这个出口一定回去调用父类构造,也简单解释了之前提到的:一个简单java类一定要保留一个无参构造方法.