目录
继承的概念
继承就是,子类从父类继承方法,使得子类有和父类一样的行为。
生活中的继承
食草动物有自己的属性和方法,同样食肉动物也有自己的属性和方法,但两者肯定都是动物,有一定的共性,同样也保留自己的个性。更形象地讲,父类是通用的,子类是具体的。
类的继承格式
class 父类 {
}
class 子类 extends 父类 {
}
为什么要继承
下面是用一个例子来更好地说明有继承这个特性:
下面是两个类,企鹅和老鼠
public class Penguin {
private String name;
private int id;
public Penguin(String myName, int myid) {
name = myName;
id = myid;
}
public void eat(){
System.out.println(name+"正在吃");
}
public void sleep(){
System.out.println(name+"正在睡");
}
public void introduction() {
System.out.println("大家好!我是" + id + "号" + name + ".");
}
}
public class Mouse {
private String name;
private int id;
public Mouse(String myName, int myid) {
name = myName;
id = myid;
}
public void eat(){
System.out.println(name+"正在吃");
}
public void sleep(){
System.out.println(name+"正在睡");
}
public void introduction() {
System.out.println("大家好!我是" + id + "号" + name + ".");
}
}
通过阅读两段代码,不难发现,两段代码存在大量的相似代码,造成代码冗余。并且更重要的是,后期的可维护性不高,因为一旦要修改代码,就要做大量重复工作。所以,我们使用继承的特性,创建一个Animal的父类:
public class Animal {
private String name;
private int id;
public Animal(String myName, int myid) {
name = myName;
id = myid;
}
public void eat(){
System.out.println(name+"正在吃");
}
public void sleep(){
System.out.println(name+"正在睡");
}
public void introduction() {
System.out.println("大家好!我是" + id + "号" + name + ".");
}
}
然后创建两个子类来继承这个父类,这样的两个子类就会更清晰、更简洁。并且代码的复用性很高,后期也更方便维护:
public class Penguin extends Animal {
public Penguin(String myName, int myid) {
super(myName, myid);
}
}
public class Mouse extends Animal {
public Mouse(String myName, int myid) {
super(myName, myid);
}
}
继承类型
- 要注意的是,Java只支持单继承和多重继承,并不支持多继承!!!
-
单继承
-
多重继承
-
不同类继承同一个类
-
不支持多继承
这里要理解一下多继承,是指子类继承多个父类,并不是指一个父类有多个子类。
继承的特性
- 继承的子类可以有父类的非private的属性、方法
- 继承的子类可以有自己特有的属性和方法(即对父类的扩展)
- 继承的子类可以使用自己的方式调用父类的方法
- Java中的继承是单继承,但是支持多重继承
- 继承会提高代码的耦合性(继承的缺点,耦合性的提高,会降低代码的独立性)
继承的关键字
-
extends
含义:当一个类使用“extends”关键字时,它表示这个类是从另一个类派生出来的,继承了父类的属性和方法。这种继承是单继承,即一个类只能有一个父类。
形象解释:可以想象成“亲子关系”。比如有一个“动物”类,它有一些基本的属性和行为,如“名字”、“年龄”、“吃东西”等。然后有一个“狗”类,它使用“extends”关键字继承了“动物”类。这就像是“狗”是“动物”的孩子,它继承了“动物”的一些基本特征和行为,同时还可以有自己的独特行为,比如“汪汪叫”。
-
implements
含义:这个关键字用于实现接口。在 Java 中,接口是一种特殊的抽象类,它只包含抽象方法和常量。当一个类使用“implements”关键字时,它表示这个类实现了某个接口,需要提供接口中所有抽象方法的具体实现。
形象解释:可以想象成“契约关系”。比如有一个“可飞”接口,它定义了一个“飞行”的方法。然后有一个“鸟”类,它使用“implements”关键字实现了“可飞”接口。这就像是“鸟”和“可飞”之间签订了一个契约,“鸟”承诺会实现“飞行”这个行为,具体怎么飞由“鸟”自己决定。
-
super和this
super:可以用来访问当前对象的父类
this:引用当前的对象
class Animal {
void eat() {
System.out.println("animal : eat");
}
}
class Dog extends Animal {
void eat() {
System.out.println("dog : eat");
}
void eatTest() {
this.eat(); // this 调用自己的方法
super.eat(); // super 调用父类方法
}
}
public class Test {
public static void main(String[] args) {
Animal a = new Animal();
a.eat();
Dog d = new Dog();
d.eatTest();
}
}
运行结果是:
animal : eat
dog : eat
animal : eat
final
final 可以用来修饰变量(包括类属性、对象属性、局部变量和形参)、方法(包括类方法和对象方法)和类。
-
修饰变量:
final int age = 25; // 一旦赋值为25,就不能再修改
// age = 30; // 这会报错,因为age是final变量
-
修饰方法:
class Animal {
final void eat() {
System.out.println("Animals eat food.");
}
}
class Dog extends Animal {
// 下面的代码会报错,因为eat()方法是final,不能被重写
// @Override
// void eat() {
// System.out.println("Dogs eat bones.");
// }
}
-
修饰类:
final class FinalClass {
void display() {
System.out.println("This is a final class.");
}
}
// 下面的代码会报错,因为FinalClass是final类,不能被继承
// class SubClass extends FinalClass {
// }
final的核心思想是“不可变性”和“不可扩展性”,它在程序设计中用于确保某些关键部分的稳定性和安全性。
构造器
子类并不会继承父类的构造器,但是会调用父类的构造器。目的是,在子类被正确创建的过程中,父类也能够被正确加载。
形象解释:可以想象一个“两层建筑”:
-
第一层是父类,第二层是子类。
-
在建造第二层之前,必须先完成第一层的建造。父类的构造器负责初始化第一层,子类的构造器负责初始化第二层。
当父类的构造器带有参数
这时,子类就会需要使用super关键字显式的调用父类的构造器:
class Parent {
int x;
//父类构造器有参数
Parent(int x) {
this.x = x;
System.out.println("Parent constructor called, x = " + x);
}
}
class Child extends Parent {
int y;
Child(int x, int y) {
super(x); // 显式调用父类的构造器
this.y = y;
System.out.println("Child constructor called, y = " + y);
}
}
public class Main {
public static void main(String[] args) {
Child obj = new Child(10, 20);
}
}
输出结果:
Parent constructor called, x = 10
Child constructor called, y = 20
当父类构造器不带参数
class Parent {
int x;
//父类构造器无参数
Parent() {
x = 10;
System.out.println("Parent constructor called, x = " + x);
}
}
class Child extends Parent {
int y;
Child() {
y = 20;
System.out.println("Child constructor called, y = " + y);
}
}
public class Main {
public static void main(String[] args) {
Child obj = new Child();
}
}
输出结果:
Parent constructor called, x = 10
Child constructor called, y = 20