Day08目标:
-
理解继承的意义及用法;
-
掌握super关键字的用法;
-
理解super在继承中的意义;
-
理解何时需要重写方法;
-
掌握方法重写的语法及特点;
-
掌握final关键字的用法
继承
继承的作用
-
生活中的继承:
-
继承财产:钱不用自己挣,自己也能花;
-
继承皇位:江山不用自己打,自己也能坐;
-
继承工作:工作不用自己找,自己也能干
-
继承??:??不用自己?,自己也能?
-
-
软件中的继承:
- 代码不用自己写,自己也能用。
// Student类
class Student{
String name;
int age;
String address;
String className;
String syuId;
void eat(){}
void sleep(){}
void study(){}
}
// Teacher类
class Teacher{
String name;
int age;
String address;
String className;
String syuId;
void eat(){}
void sleep(){}
void study(){}
}
// Doctor类
class Doctor{
String name;
int age;
String address;
String className;
String syuId;
void eat(){}
void sleep(){}
void study(){}
}
这种写法是我们之前用的,我们发现这样太麻烦了,不符合一个优秀程序员的编程要求,于是:
// person类
class Person{
String name;
int age;
String address;
void eat(){}
void sleep(){}
}
// Student类继承(extends)Person类
class Student extends Person {
String className;
String stuId;
void study(){}
}
// Teacher类继承(extends)Person类
class Teacher extends Person {
String salary;
void teach(){}
}
// Doctor类继承(extends)Person类
class Doctor extends Person {
String title;
void cut(){}
}
/*
Student zg = new Student();
zg能访问:Student和Person类中的所有方法
*/
继承
-
作用:实现代码复用
-
语法:通过
extends
实现继承 -
Person这个被继承的类,我们叫:“超类、基类、父类”;去用Person这个类的类叫做“派生类、子类”。
-
超类、基类、父类:共有的属性和行为;
-
派生类、子类:特有的属性和行为;
-
派生类可以访问派生类和超类,超类不能访问派生类;(孩子可以继承父亲,但是父亲不能继承儿子)
-
-
单一继承 —— 一个超类可以有多个派生类,但一个派生类只能有一个超类(一个孩子只能有一个亲爹)
-
泛化:从程序的设计角度而言叫做泛化,从代码实现角度而言叫继承,泛化就是继承
-
继承要符合is的关系
-
继承具有传递性
class Aoo { -------- 可以访问a
int a;
}
class Boo extends Aoo { --------- 可以访问b、a
int b;
}
class Coo extends Boo { --------- 可以访问c、b、a
int c;
}
- 继承的是父类的成员变量和普通方法,不包括构造方法,父类的构造方法是被子类能过super来调用的
super
super关键字
-
作用:指代当前对象的超类对象,类似
this
super.成员变量名
:访问超类的成员变量
class Student extends Person{ String className; String stuId; Student(String name, int age, String address, String className, String stuId) { super.name = name; super.age = age; super.address = address; this.className = className; this.stuId = stuId; } }
-
使用情况:如果子类、父类中有同名变量时,我们要用父类的变量,必须用
super
,平时用this
就可以了,很难出现用到super
的情况,因为我们既然父类中已经有这个变量了,何必还要在子类再来一个? -
super.方法名()
:调用超累的方法 —— 方法的重写讲,就在这一章 -
super()
:调用超类的构造方法
super与继承的关系
-
Java规定:构造子类前必须先构造父类!
-
为了保证这个规定,Java做了两种处理:
- 在子类的构造方法中若没有调用父类的构造方法,则默认
super()
调用超类的无参构造方法,无论你在子类是否用到了父类,只要你继承了,父类就必须先走一遍。
class Aoo{ Aoo() { System.out.println("父类构造方法"); } } class Boo extends Aoo{ Boo() { // super(); System.out.println("子类无参构造方法") } }
- 在子类的构造方法中若自己调用了超类的构造方法,则不再默认提供
class Coo { Coo (int a) { } } class Doo extends Coo { } // 我们发现报错了,可以思考一下报错原因吗
class Coo { Coo (int a) { } } class Doo extends Coo { // 如下代码是默认的但是被隐藏 Doo { // 如果我们的类中没有构造方法则自动给无参构造 super(); // 默认一定调用父类构造方法,但是父类的构造方法中有参数,而子类没有给父类值 } } // 我们可以改成
class Coo { Coo (int a) { } } class Doo extends Coo { Doo { super(5); } } // 现在有参数了,子类Doo自己调用父类Coo
- 在子类的构造方法中若没有调用父类的构造方法,则默认
-
接下来我们让这段代码更为简单,在父类构造方法,在子类用super();方法,把活交给父亲干,子类只需要用就可以了!
Person.java
package day08;
// Person类
public class Person {
String name;
int age;
String address;
Person(){
}
Person(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
void eat(){
System.out.println(name + "正在吃...");
}
void sleep(){
System.out.println(name + "正在睡觉...");
}
void sayHi(){
System.out.println("大家好!我叫" + name + ",今年" + age + "岁了,家住" + address);
}
}
Student.java
package day08;
// Student类
public class Student extends Person{
String className;
String stuId;
Student() {
}
Student(String name, int age, String address, String className, String stuId) {
super(name, age, address); // 把该父类做的让父类做,子类只需要用
this.className = className; // 该子类做的子类还得做
this.stuId = stuId;
}
void study(){
System.out.println(name + "正在学习...");
}
}
Teacher.java
package day08;
// Teacher类
public class Teacher extends Person{
double salary;
Teacher(){
}
Teacher(String name, int age, String address, double salary) {
super(name, age, address); // 把该父类做的让父类做,子类只需要用
this.salary = salary; // 该子类做的子类还得做
}
void teach(){
System.out.println(name + "正在上课......");
}
}
Doctor.java
package day08;
// Doctor类
public class Doctor extends Person{
String title;
Doctor(){
}
Doctor(String name, int age, String address, String title){
super(name, age, address); // 把该父类做的让父类做,子类只需要用
this.title = title; // 该子类做的子类还得做
}
void cut(){
System.out.println(name + "正在做手术...");
}
}
新建一个ExtendsTest.java
package day08;
// Extends全系列测试类
public class ExtendsTest {
public static void main(String[] args) {
// 实例化:学生对象无参构造
Student student = new Student();
student.name = "张禹垚";
student.age = 21;
student.address = "齐齐哈尔";
student.className = "JSD2407";
student.stuId = "00109320";
// 调用父类方法及子类方法(子类继承父类)
student.sayHi();
student.study();
student.eat();
student.sleep();
System.out.println("-------------------------------------");
// 实例化:学生对象有参构造
Student zyy = new Student("张禹垚", 21,
"齐齐哈尔", "JSD2407",
"00109320");
// 调用父类方法及子类方法(子类继承父类)
zyy.sayHi();
zyy.study();
zyy.sleep();
zyy.eat();
System.out.println("-------------------------------------");
// 实例化:Doctor对象有参构造
Doctor doctor = new Doctor("张禹垚", 21,
"北京", "院长");
// 调用父类方法及子类方法(子类继承父类)
doctor.sayHi();
doctor.sleep();
doctor.eat();
doctor.cut();
System.out.println("-------------------------------------");
// 实例化:Teacher对象有参构造
Teacher teacher = new Teacher("张禹垚", 21,
"天津", 10000.0);
// 调用父类方法及子类方法(子类继承父类)
teacher.sayHi();
teacher.eat();
teacher.sleep();
teacher.teach();
System.out.println("-------------------------------------");
// 父类不能访问子类(父亲不能继承儿子)
// 实例化:Person父类无参构造
Person person = new Person();
person.address = "上海";
person.name = "张禹垚";
person.age = 21;
// 调用父类方法(父类不继承):可以!
person.sayHi();
person.eat();
person.sleep();
// 调用子类方法(父类继承子类):不行!
// person.cut(); // 编译错误:Cannot resolve method 'cut' in 'Person'
}
}
方法的重写
方法的重写
方法的重写(Overriding)是面向对象编程中的一个重要概念,尤其在Java中,它体现了多态性。当一个子类继承(或实现)一个父类(或接口)时,可以对父类的某个方法进行重写,以提供自己特定的实现。
说白了,例如这个例子:
class Restaurant {
void makeFood () {
System.out.println("做中餐");
}
}
// 我继承参观后还是想做中餐 ———————————— 不需要重写
class Aoo extends Restaurant {
}
// 我继承参观后想改做西餐 —————————————— 需要重写
class Boo extends Restaurant {
void makeFood() {
System.out.println("做西餐");
}
}
// 我继承参观后想在中餐基础上加入西餐 —————————— 需要重写(先super中餐,再加入西餐)
class Coo extends Restaurant {
void makeFood() {
super.makeFood();
System.out.println("做西餐");
}
}
final
-
表示最终的、不可改变的
-
特点:
-
修饰变量:此变量不可改变
-
修饰方法:方法不能被重写
-
修饰类:类不能被继承
-
final修饰变量
- final修饰变量,表示变量不能被改变。
class Eoo {
final int a = 5;
int b = 6;
void test(){
a = 55; // 编译错误,final修饰的变量不能被改变
b = 66;
final int c = 8;
c = 88; // 编译错误
}
}
- final修饰方法,表示方法不能被重写
class Foo {
final void show() {
void test() {
}
}
}
class Goo extends Foo {
// void show() { // 编译错误,final修饰方法不能被重写
void test() {
}
}
- final修饰类,表示类不能被继承
final class Hoo {
}
class Ioo extends Hoo { // final修饰的类不能被继承
}
- JDK中一些类被定义为final的:String、Math、Integer、Double等