继承的概念
- 当多个类之间有相同的特征和行为时,可以将相同的内容提取出来组成一个公共类,让多个类吸收公共类中已有特征和行为而在多个类型只需要编写自己独有特征和行为的机制,叫做继承。
- 在Java语言中使用
extends
来表示继承关系。如public class Worker extends Person{}
表示Worker类继承自Person类,其中Person类叫做超类、父类、基类;Worker类叫做派生类、子类、孩子类。 - 使用继承提高了代码的复用性,可维护性及扩展性,是多态的前提条件。
继承的特点
- 子类不能继承父类的构造方法和私有方法,但私有成员变量可以被继承只是不能直接访问。
- 无论使用何种方式构造子类的对象时都会自动调用父类的无参构造方式,来初始化从父类中继承的成员变量,相当于再构造方法的第一行增加代码
super()
的效果。 - 使用继承必须满足逻辑关系:
子类 is a 父类
,也就是不能滥用继承。 - Java语言中只支持单继承不支持多继承,也就是说一个子类只能有一个父类,但是一个父类可以有多个子类.
方法重写的概念
- 从父类中继承下俩的方法不满足子类的需求时,就需要在子类中重新写一个和父类一样的方法来覆盖从父类中继承下来的版本,该方式就叫做方法的重写
Override
。
方法重写的原则
- 要求方法名相同、参数列表相同以及返回值类型相同,从Java5开始允许返回子类类型。
- 要求方法的访问权限不能变小,可以相同或者变大。
- 要求方法不能抛出更大的异常(异常机制)。
public class Person {
private String name;
private int age;
public Person() {
System.out.println("Person()");
}
public Person(String name, int age) {
System.out.println("Person(String,int)");
setName(name);
setAge(age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if(age > 0 && age < 150) {
this.age = age;
} else {
System.out.println("年龄不合理!!!");
}
}
void show() {
System.out.println("我是" + getName() + ",今年" + getAge() + "岁了");
}
public void eat(String food) {
System.out.println(food + "真好吃!");
}
public void play(String game) {
System.out.println(game + "真好玩!");
}
}
public class Worker extends Person {
private int salary;
public Worker() {
super();
System.out.println("Worker()");
}
public Worker(String name, int age, int salary) {
super(name, age);
System.out.println("Worker(String,int,int)");
setSalary(salary);
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
if(salary > 0){
this.salary = salary;
} else {
System.out.println("薪资不合理!!!");
}
}
public void work() {
System.out.println("今天的砖头有点烫手!");
}
@Override
public void show() {
super.show();
System.out.println("我的薪水是:" + getSalary());
}
}
public class WorkerTest {
public static void main(String[] args) {
Worker w1 = new Worker();
w1.show();
System.out.println("----------------------");
Worker w2 = new Worker("张飞", 30, 3000);
w2.show();
w2.eat("豆芽");
w2.play("王者荣耀");
w2.work();
}
}
案例题目:Animal类和Dog类的封装与测试
- 编程实现Animal类的封装,特征有:名字和毛色,要求提供打印所有特征的方法。
- 编程实现Dog类的封装并继承自Animal类,该类的特征有:牙齿数量,要求提供打印所有特征的方法。
- 编程实现DogTest类,在main方法中分别使用无参和有参方式构造Dog类型对象并打印特征
package com.lagou.task08;
public class Animal {
private String name;
private String color;
public Animal() { }
public Animal(String name, String color) {
setName(name);
setColor(color);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public void show() {
System.out.println("名字:" + getName() + ",颜色:" + getColor());
}
}
package com.lagou.task08;
public class Dog extends Animal {
private int tooth;
public Dog() {
super();
}
public Dog(String name, String color, int tooth) {
super(name, color);
setTooth(tooth);
}
public int getTooth() {
return tooth;
}
public void setTooth(int tooth) {
if(tooth > 0) {
this.tooth = tooth;
} else {
System.out.println("牙齿的数量不合理!!!");
}
}
@Override
public void show() {
super.show();
System.out.println("牙齿的数量是:" + getTooth());
}
}
package com.lagou.task08;
public class DogTest {
public static void main(String[] args) {
Dog d1 = new Dog();
d1.show();
System.out.println("--------------------");
Dog d2 = new Dog("旺财","白色",10);
d2.show();
}
}
又见构造块与静态代码块(笔试)
- 先执行父类的静态代码块,再执行子类的静态代码块
- 执行父类的构造块,执行父类的构造方法体
- 执行子类的构造块,执行子类的构造方法体
package com.lagou.task08;
public class SuperTest {
{
System.out.println("SuperTest类中的构造块!");
}
static {
System.out.println("SuperTest类中的静态代码块!");
}
public SuperTest() {
System.out.println("SuperTest类中的构造方法体!");
}
}
package com.lagou.task08;
public class SubSuperTest extends SuperTest {
{
System.out.println("=====SubSuperTest类中的构造块!");
}
static {
System.out.println("=====SubSuperTest类中的静态代码块!");
}
public SubSuperTest() {
System.out.println("=====SubSuperTest类中的构造方法体!");
}
public static void main(String[] args) {
SubSuperTest sst = new SubSuperTest();
}
}