文章目录
- 引出继承
- 继承的概念
- 继承的限制
- 一个子类只能够继承一个父类,存在单继承局限。
- 无法直接继承私有属性
- 继承关系中,先构造父类,再构造子类
引出继承
Animal类
class Animal {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Reptile类:
class Reptile {// 爬行动物
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void climb() {
System.out.println("爬行...");
}
}
这两个程序存在着大量的重复,出现了冗余代码。为了解决这个问题,我们就可以使用extends关键字。
继承的概念
继承是面向对象最显著的一个特性。继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。
继承语法
class 子类 extends 父类 { /* 类体 */}
子类又被称为派生类; 父类又被称为超类或者基类
观察继承的基本实现:
class Animal {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
}
class Reptile extends Animal {// 爬行动物
public Reptile(String name, int age) {
super(name, age);
}
public void climb() {
System.out.println("爬行");
}
}
public class Test {
public static void main(String[] args) {
Reptile clion = new Reptile("狮子", 4);
System.out.println(clion.getName() + " " + clion.getAge() + " 岁");
}
}
/*
执行结果
狮子 4 岁
*/
通过代码可以发现,子类(Reptile)并没有定义任何属性,而在主类中所使用的属性都是由Animal类定义的,所以可以得知,继承父类之后可以使用父类的属性和方法。
继承的限制
虽然继承可以进行类功能的扩充,但是其在定义的时候也是会存在若干种限制的。
一个子类只能够继承一个父类,存在单继承局限。
错误的写法:
class A {}
class B {}
class C extends A,B {} // 一个子类继承了两个父类
上面C类同时继承了A类和B类,但是在Java中并不支持这种操作,C++是支持的。
正确的写法:
class A {}
class B extends A {}
class C extends B {}
C 类继承B类,而B类又是继承A类,这种操作称为多层继承。
无法直接继承私有属性
可以通过继承公有成员函数访问私有成员变量。
class A {
private String password;
public void setPassword(String msg) {
this.password = msg;
}
public String getPassword() {
return this.password;
}
}
class B extends A {
public void print() {
//System.out.println(password); error
}
}
public class TestDemo {
public static void main(String args[]) {
B b = new B();
b.setPassword("123");
System.out.println(b.getPassword());
}
}
此时对于A类之中的password这个私有属性发现无法直接进行访问,但是可以通过setter、getter方法间接的进行操作。
继承关系中,先构造父类,再构造子类
在继承关系之中,如果要实例化子类对象,会默认先调用父类构造,为父类之中的属性初始化,之后再调用子类构造,为子类之中的属性初始化,即:默认情况下,子类会找到父类之中的无参构造方法。
class A {
public A() { // 父类无参构造
System.out.println("父类构造");
}
}
class B extends A {
public B() {
System.out.println("子类构造");
}
}
public class TestDemo {
public static void main(String args[]) {
B b = new B();
}
}
/*
执行结果
父类构造
子类构造
*/
这个时候虽然实例化的是子类对象,但是发现它会默认先执行父类构造,调用父类构造的方法体执行,而后再实例化子类对象,调用子类的构造方法。而这个时候,对于子类的构造而言,就相当于隐含了一个super()的形式:
class B extends A {
public B() {
super();
System.out.println("子类构造");
}
}
如果父类没有无参构造,那么就要显示使用super调用父类的构造方法,先帮助父类完成构造。
class A {
public A(String s) { // 父类无参构造
System.out.println("父类构造" + s);
}
}
class B extends A {
public B(String s) {
super(s);
System.out.println("子类构造");
}
}
public class TestDemo {
public static void main(String args[]) {
B b = new B();
}
}