概述
本文深入探討面向對象編程的核心概念,包括繼承、方法重寫、this
和super
關鍵字的使用,以及抽象類和方法的定義與實現。通過本文的學習,你將能夠:
- 理解繼承的優勢。
- 掌握繼承的使用方法。
- 了解繼承后成員變量和成員方法的訪問特點。
- 掌握方法重寫及其應用場景。
- 學會使用
this
關鍵字調用當前對象的成員。 - 學會使用
super
關鍵字調用父類的成員。 - 定義抽象方法和抽象類。
- 重寫抽象方法。
第一章:繼承
1. 什么是繼承
繼承是一種代碼復用機制,通過將共通代碼抽取到父類中,子類可以直接繼承父類的功能。在Java中,使用extends
關鍵字實現繼承。
注意點:
- 子類可以繼承父類的非私有成員,但不能訪問私有成員。
- 構造方法不能被繼承。
學習繼承:
- 應從能否“使用”的角度來學習繼承,而非“擁有”。
2. 繼承如何使用
定義一個父類,將重復代碼放入其中。然后,定義子類繼承父類,通過extends
關鍵字。創建子類對象后,可以直接使用父類中的非私有成員。
public class Employee {String name;int age;public void work(){System.out.println("工作");}private void eat(){System.out.println("員工要干飯");}
}public class Teacher extends Employee{}public class Manager extends Employee{
}
3. 繼承中,成員變量和成員方法的訪問特點
成員變量
- 不重名情況: 子類和父類可以擁有同名成員變量,但訪問時會根據對象類型決定訪問哪個變量。
public class Fu {int numFu = 100;
}public class Zi extends Fu{int numZi = 10;
}public class Test01 {public static void main(String[] args) {Fu fu = new Fu();System.out.println(fu.numFu);//父類中的numFuZi zi = new Zi();System.out.println(zi.numZi);System.out.println(zi.numFu);//繼承了父類,可以使用父類中非私有成員}
}
- 重名情況: 當子類和父類成員變量重名時,訪問時會優先使用子類的成員變量,如果子類沒有,則訪問父類的成員變量。
public class Fu {int numFu = 100;int num = 10000;
}public class Zi extends Fu{int numZi = 10;int num = 1000;
}
成員方法
- 方法調用: 看
new
的對象是誰,優先調用誰的方法。如果子類沒有該方法,則會尋找父類中的方法。
public class Fu {public void methodFu(){System.out.println("我是父類中的methodFu");}public void method(){System.out.println("我是父類中的method方法");}
}public class Zi extends Fu{public void methodZi(){System.out.println("我是子類中的methodZi方法");}public void method(){System.out.println("我是子類中的method方法");}
}
4. 方法的重寫
方法重寫是指子類中有一個與父類方法名和參數列表相同的方法。使用@Override
注解可以檢測是否為重寫方法。
注意事項:
- 子類重寫父類方法之后,權限必須要保證大于等于父類權限(權限指的是訪問權限)
public -> protected -> 默認 -> private - 子類方法重寫父類方法,方法名和參數列表要一樣
- 私有方法不能被重寫,構造方法不能被重寫,靜態方法不能被重寫
- 子類重寫父類方法之后,返回值類型應該是父類方法返回值類型的子類類型
public class Fu {public void methodFu(){System.out.println("我是父類中的methodFu方法");}public void method(){System.out.println("我是父類中的method方法");}void method01(){}/* public static void method02(){}*/public Fu method03(){return null;}
}
public class Zi extends Fu{public void methodZi(){System.out.println("我是子類中的methodZi方法");}@Overridepublic void method(){System.out.println("我是子類中的method方法");}@Overridepublic void method01(){}/* public static void method02(){}*/@Overridepublic Zi method03(){return null;}
}
使用場景: 功能升級改造,子類需要對父類中已經實現好的功能進行重新改造
public class Fu {public void methodFu(){System.out.println("我是父類中的methodFu方法");}public void method(){System.out.println("我是父類中的method方法");}
}public class Zi extends Fu{public void methodZi(){System.out.println("我是子類中的methodZi方法");}@Overridepublic void method(){System.out.println("我是子類中的method方法");}
}
第二章:super
和this
1. 繼承中構造方法的特點
- 當創建子類對象時,會先初始化父類,即執行父類的構造方法。
public class Fu {public Fu(){System.out.println("我是父類中的無參構造");}
}public class Zi extends Fu{public Zi(){super();System.out.println("我是子類中的無參構造");}public Zi(int i){super();System.out.println("我是子類中的有參構造");}
}
2. super
和this
的具體使用
super
- 調用父類構造方法: 在子類構造方法中使用
super()
調用父類無參構造,或使用super(實參)
調用父類有參構造。 - 調用父類成員變量和方法: 使用
super.成員變量名
和super.成員方法名(實參)
。
public class Fu {int num = 10;public Fu(){System.out.println("我是父類中的無參構造");}public Fu(int data){System.out.println("我是父類中的有參構造");}public void method(){System.out.println("我是父類中的method方法");}
}public class Zi extends Fu{int num = 100;public Zi(){super();System.out.println("我是子類中的無參構造");}public Zi(int num){super(10);System.out.println("我是子類中的有參構造");}public void method(){super.method();System.out.println("我是子類中的method方法");System.out.println(num);System.out.println(super.num);}
}
this
- 調用當前對象的構造方法: 在構造方法中使用
this()
調用當前對象的無參構造,或使用this(實參)
調用當前對象的有參構造。 - 調用當前對象的成員變量和方法: 使用
this.成員變量名
和this.成員方法名(實參)
。
public class Person {int num = 10;public Person(){this();System.out.println("我是Person中的無參構造");}public Person(int data){this();System.out.println("我是Person中的有參構造");}public void method(){int num = 20;System.out.println(num);System.out.println(this.num);this.method01();System.out.println("我是Person類中的method方法");}public void method01(){System.out.println("我是Person類中的method01方法");}
}
3. 繼承的特點
- Java只支持單繼承,不支持多繼承。
- 繼承支持多層繼承。
- 一個父類可以有多個子類。
- 構造方法、私有方法和靜態方法不能被繼承或重寫。
第三章:抽象
1. 抽象的介紹
抽象類和抽象方法是面向對象編程中用來表達共性和多樣性的工具。抽象方法沒有具體實現,必須在子類中重寫。
關鍵字:
abstract
用于定義抽象方法和抽象類。
注意事項:
- 抽象方法所在的類必須是抽象類。
- 子類必須重寫父類中的所有抽象方法,除非子類也是抽象類。
- 抽象類不能被直接實例化,只能通過子類對象來調用重寫的方法。
public abstract class Animal {public abstract void eat();public abstract void drink();
}public class Dog extends Animal{@Overridepublic void eat() {System.out.println("狗啃骨頭");}@Overridepublic void drink() {System.out.println("狗喝水");}
}
2. 抽象的注意事項
- 抽象類不能直接創建對象,只能創建非抽象子類的對象。
- 抽象類中可以包含成員變量、構造方法和成員方法。
public abstract class Employee {private String name;private int age;public Employee() {}public Employee(String name, int age) {this.name = name;this.age = 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 abstract void work();
}
第四章:綜合案例
本章節通過一個IT公司的員工體系案例,展示了如何定義類、指定繼承關系,并實現工作方法的調用。
案例描述:
某IT公司根據員工的工作內容,劃分了不同的部門和職位。每個員工都有員工編號和姓名,并執行他們負責的工作。
類的定義和繼承關系:
Employee
:基類,包含員工編號和姓名。Developer
:抽象類,繼承自Employee
,代表研發部員工。JavaEE
、Android
:具體類,繼承自Developer
,代表不同的研發工程師。Maintainer
:抽象類,繼承自Employee
,代表維護部員工。Network
、Hardware
:具體類,繼承自Maintainer
,代表不同的維護工程師。
對象創建和方法調用:
通過創建具體工程師類的對象,調用work
方法,展示每個員工的工作內容。
public abstract class Employee {private int id;private String name;public Employee() {}public Employee(int id, String name) {this.id = id;this.name = name;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public abstract void work();
}public abstract class Developer extends Employee{
}public class JavaEE extends Developer{@Overridepublic void work() {System.out.println("員工號為:"+this.getId()+"的"+this.getName()+"正在開發網站");}
}public class Android extends Developer{@Overridepublic void work() {System.out.println("員工號為:"+this.getId()+"的"+this.getName()+"正在開發app");}
}public class Test01 {public static void main(String[] args) {JavaEE javaEE = new JavaEE();javaEE.setId(1);javaEE.setName("濤哥");javaEE.work();System.out.println("===============");Android android = new Android();android.setId(2);android.setName("金蓮");android.work();}
}