day01 【複習回顧、繼承、抽象類模板設計模式】
主要內容
1.面向對象回顧
2.封裝(基礎班),繼承(今天),多態(明天+後天)
3.設計模式:模板設計模式
第一章 複習
1.1 如何定義類
格式:
public class 類名{
//成員變量
數據類型 成員變量名;
//成員方法
public 返回值類型 方法名(參數列表){
方法體;
return 返回值;
}
}
1.2 如何通過類創建對象
格式:
類名 對象名 = new 構造方法名(具體參數);
1.3 封裝
-
封裝的步驟
a.給成員變量加上private b.爲每個成員變量,提供一組getter和setter
-
封裝的代碼實現
public class Dog { //成員變量 private int age; private String name; //提供getter和setter //alt+insert 省略... //成員方法:吠 public void bark() { System.out.println("小狗嗷嗷叫~~~"); } } public class TestDog { public static void main(String[] args) { //創建對象 Dog dd = new Dog(); //封裝之後,我們需要通過調用get和set方法來取值或者賦值 System.out.println(dd.getName()); System.out.println(dd.getAge()); //調用方法 dd.bark(); } }
1.4 構造器(構造方法)
-
構造器的作用
給創建出的對象的成員變量初始化!!
-
構造器的格式
格式: public 類名(){ } public 類名(參數列表){ 給對象中成員變量賦值 }
-
構造器的使用
無參構造: 類名 對象名 = new 構造方法名(); 有參構造: 類名 對象名 = new 構造方法名(實際參數); 例如: Dog dd = new Dog(); //使用無參構造 Dog dd2 = new Dog(10,"旺財");
1.5 this關鍵字
-
this關鍵字代表什麼
代表當前對象的引用: 當前對象,成員方法由哪個對象調用的,方法中的this就代碼那個對象
-
this在代碼中的應用
a.在set方法中使用到this,給同名的成員變量賦值 public void setAge(int age) { this.age = age; } b.在構造方法中使用到this,給同名的成員變量賦值 public Dog(int age, String name) { this.age = age; this.name = name; }
1.6 匿名對象
-
什麼是匿名對象
沒有名字的對象!!!! 匿名對象是指只new對象,但是不用對象名來接收 正常對象: Dog d = new Dog(); 匿名對象: new Dog(); 注意: 這裏匿名是指沒有使用對象名接收,而不是對象中沒有name屬性
-
匿名對象的使用場景
當一個對象我們只需要使用一次時就可以選擇使用匿名對象 public class NiMingDemo { public static void main(String[] args) { //需求:編寫一個程序,要求用戶輸入他的年齡 System.out.println("請輸入您的年齡:"); //使用正常對象 // Scanner sc = new Scanner(System.in); // int age = sc.nextInt();//ctrl+alt+v 或者 .var 自動接收方法返回值 //使用匿名對象 int age = new Scanner(System.in).nextInt(); System.out.println("您剛剛輸入的年齡是:" + age); } }
第二章 繼承
-
引入案例
假如我們要定義如下類: 學生類,老師類和班主任類,分析如下: 1. 學生類 屬性:姓名,年齡 行爲:喫飯,睡覺 2. 老師類 屬性:姓名,年齡,薪水 行爲:喫飯,睡覺,教書 3. 班主任 屬性:姓名,年齡,薪水 行爲:喫飯,睡覺,管理 如果我們定義三個類,每個類都有姓名,年齡,喫飯,睡覺
2.1 繼承的概念
在一個已知類A的基礎上,創建新類B的過程,稱之爲繼承
這裏類A,稱爲父類,基類,超類,英文名SuperClass
這裏類B,稱爲子類,派生類,英文名SubClass
2.2 繼承的格式
格式:
public class 父類{
//成員變量
//成員方法
}
public class 子類 extends 父類{
子類中就自動繼承了父類中的成員變量和成員方法
子類也可以添加自己的成員變量和成員方法
}
2.3 繼承的案例
父類:人類
public class Human {
//人類的共同成員變量和成員方法
int age;
String name;
public void eat(){
System.out.println("我喫蝙蝠...");
}
public void sleep(){
System.out.println("我聽課睡着了...");
}
}
學生類:
public class Student extends Human{
}
老師類:
public class Teacher extends Human {
//薪水
double salary;
//教書
public void teach(){
System.out.println("#$%&*($%^*()%&*...");
}
}
班主任類:
public class BanZhuRen extends Human{
//薪水
double salary;
//管理
public void manager(){
System.out.println("開播了,趕緊起牀~~~~");
}
}
測試類
public class TestDemo {
public static void main(String[] args) {
//1.測試Student類
Student s1 = new Student();
System.out.println(s1.age);
System.out.println(s1.name);
s1.eat();
s1.sleep();
//2.測試Teacher類
Teacher t1 = new Teacher();
System.out.println(t1.age);
System.out.println(t1.salary);
t1.eat();
t1.teach();
//3.班主任類...自己寫完
}
}
-
繼承好處總結
a.提高代碼的複用性 b.類與類之間有了關係,爲以後學的"多態"提供了前提
2.4 子類不能繼承的內容
a.父類的構造方法子類無法繼承!! (因爲構造方法和類名是一樣的)
b.父類的私有成員,子類可以繼承但是不能直接使用!!!(間接使用)
父類:
public class Animal {
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Animal() {
}
public Animal(int age) {
this.age = age;
}
}
子類:
public class Dog extends Animal {
//構造方法無法繼承
//私有成員能繼承,但是子類無法直接訪問
}
測試類:
public class TestDog {
public static void main(String[] args) {
//1.創建Dog對象
Dog d = new Dog();
//2.構造方法無法繼承
//Dog d1 = new Dog(10); //報錯!!
//3.私有成員可以繼承,但是無法直接訪問
//d.age; //錯誤,無法直接訪問
//比如:
//古代皇帝,皇帝駕崩了,太子繼位,
//皇帝江山屬於太子,但是皇帝妃子,太子也繼承了叫額娘,但是不能用!!
//4.私有成員我們可以間接訪問
//我們通過 get和set方法,間接訪問私有成員
d.setAge(10);
int age = d.getAge();
System.out.println("獲取到age:"+age);
}
}
2.5 繼承後的特點——成員變量
a.當子父類的成員變量不同名時,訪問成員變量時沒有歧義,寫哪個變量名就是訪問哪個變量
b.當子父類的成員變量同名時,在子類中會根據就近原則,優先訪問子類自己的那個成員變量
c.如果我就想訪問父類的成員變量,能否做到???
可以,在子類的方法中,使用super.變量名,就會訪問父類中那個成員變量!
/**
* 父類
*/
public class Fu {
// int numFu = 10;
int num = 10;
}
/**
* 子類
*/
public class Zi extends Fu{
// int numZi = 99;
int num = 99;
//展示
public void show() {
//子父類成員變量不同名
// System.out.println(numZi); // 99
// System.out.println(numFu); // 10
//子父類成員變量同名
//就近原則,優先訪問子類自己的成員變量
System.out.println(num); // 99
//如果就想訪問父類的num能否做到??
//使用Java提供的另外一個關鍵字
System.out.println(super.num); //10
}
}
public class TestDemo {
public static void main(String[] args) {
//1.創建Zi對象
Zi zz = new Zi();
//2.調用方法
zz.show();
}
}
2.6 繼承後的特點——成員方法[重點]
a.當子父類的成員方法不同名時,調用成員方法時沒有歧義,寫哪個方法名就是調用哪個方法
b.當子父類的成員方法同名時,使用子類對象調用該方法,根據就近原則,優先調用子類自己的那個成員方法
c.如果我就想通過子類對象,調用父類中的那個同名方法,能做到嗎???
不能做到!!
但是可以在子類的方法中,使用super.方法名()調用父類那個同名方法!!!
/**
* 父類
*/
public class Fu {
// public void showFu() {
// System.out.println("Fu類的show....");
// }
public void show() {
System.out.println("Fu類的show....");
}
}
/**
* 子類
*/
public class Zi extends Fu {
// public void showZi(){
// System.out.println("Zi類的show...");
// }
public void show(){
//在子類中可以使用super
System.out.println("Zi類的show...");
super.show();
}
}
public class TestDemo {
public static void main(String[] args) {
//1.創建子類對象
Zi zz = new Zi();
//2.調用方法
//子父類成員方法不同名
// zz.showZi(); //Zi類的show...
// zz.showFu(); // Fu類的show....
//子父類成員方法同名
//就近原則,優先子類自己的show方法
zz.show(); // Zi類的show...
//無法做到直接通過子類對象,super去調用父類的同名方法
//zz.super.show(); //報錯!!!因爲在測試類使用super,並不是Fu類,而是指測試類的父類
//可以在子類的show方法中,使用super.show()調用父類的同名方法
//記住: super關鍵字只能在子類內部使用
}
}
2.7 重寫的概念和應用
方法的重載(overload):
在同一個類中,出現了方法名一樣,但是參數列表(參數個數|參數類型|參數順序)不一樣的各種方法,稱爲方法的重載
方法的重寫(override):
在繼承關係中,子類中出現了一個和父類除了方法體,其他一模一樣的方法,稱爲方法的重寫
方法重寫的具體應用:
子類繼承父類時,會繼承父類的成員方法,那麼當子類發現繼承過來的方法功能不足或者不適用時,子類就可以重寫該方法,重新實現自己需要的方法體即可
/**
* 動物類
*/
public class Animal {
public void eat(){
System.out.println("動物在喫");
}
public void sleep(){
System.out.println("動物在睡");
}
}
/**
* 狗類
*/
public class Dog extends Animal{
//當子類繼承父類的方法後,發現父類的方法功能不足或者不適用,我們可以重寫
public void eat(){
System.out.println("狗狗舔着喫...");
}
public void sleep(){
System.out.println("狗狗趴着睡...");
}
}
2.8 @Override註解
@Xxxx 這種東西,我們稱爲註解,英文名Annotation
@Override 此註解叫做方法重寫註解,
主要作用就是檢查重寫的方法是否格式正確(和父類的除了方法體一模一樣)
/**
* 動物類
*/
public class Animal {
public void eat(){
System.out.println("動物在喫");
}
public void sleep(){
System.out.println("動物在睡");
}
}
/**
* 狗類
*/
public class Dog extends Animal{
//當子類繼承父類的方法後,發現父類的方法功能不足或者不適用,我們可以重寫
@Override //加上此註解,可以幫助我們檢測eat方法重寫的是否正確
public void eat(){
System.out.println("狗狗舔着喫...");
}
@Override //加上此註解,可以幫助我們檢測eat方法重寫的是否正確
public void sleep(){
System.out.println("狗狗趴着睡...");
}
}
2.9 方法重寫的注意事項
a.方法重寫是發生在子父類之間的關係
b.子類方法重寫父類方法,必須要保證權限大於等於父類權限(一般來說,父類方法寫啥權限,子類也寫啥權限)
Java中有四大權限,從大到小依次爲:
public protected 不寫(默認|default) private
c.方法重寫,除了方法體其他的都要和父類一模一樣(雖然權限可以不一樣,但是一般我們也寫一樣的權限)
2.10 繼承後的特點——構造方法
-
構造方法特點介紹
a.子類能否繼承父類的構造方法?? 子類是無法繼承父類的構造方法 b.在子類的"任何構造方法"的"第一行",都有默認一句代碼"super()",代表調用父類的無參構造
-
構造方法案例演示
/** * 父類 */ public class Person { int age; String name; public Person() { System.out.println("Person的無參構造..."); } } /** * 子類 */ public class Worker extends Person { //工資 double salary; //構造方法 public Worker(){ //默認有一句代碼 super(); System.out.println("Worker的構造方法"); } public Worker(double salary){ //默認有一句代碼 super(); this.salary = salary; System.out.println("Worker的salary構造方法"); } } public class TestDemo { public static void main(String[] args) { //1.創建Worker對象 // Worker w = new Worker(); // 調用子類無參構造,子類無參構造中調用父類的無參構造 Worker w = new Worker(3000); // 調用子類有參構造,子類有參構造中調用父類的無參構造 } }
-
構造方法總結
a.子類的任何構造,第一行都會調用父類的無參構造 b.子類的構造方法第一行,super是默認存在的,可以省略不寫,但是不寫不代表沒有!!!
2.11 super(參數)和this(參數)
-
案例引入
/** * 父類 */ public class Person { int age; String name; public Person() { System.out.println("Person的無參構造..."); } public Person(int age, String name) { this.age = age; this.name = name; System.out.println("Person有參構造"); } } /** * 子類 */ public class Worker extends Person { //工資 double salary; //構造方法 public Worker(){ //默認有一句代碼 super(); System.out.println("Worker的構造方法"); } public Worker(double salary){ //默認有一句代碼 super(); this.salary = salary; System.out.println("Worker的salary構造方法"); } //子類的構造中默認第一行調用父類無參構造 //但是我們可以手動修改super()代碼,讓他調用有參構造 public Worker(int age,String name,double salary){ //調用父類的有參構造 super(age,name); this.salary = salary; } } public class TestDemo { public static void main(String[] args) { //1.創建Worker對象 Worker w = new Worker(20,"小王吧",4000); //2.打印對象中屬性值 System.out.println(w.name); System.out.println(w.age); System.out.println(w.salary); } }
-
super(…)用法演示
super() 代表調用父類的無參構造,默認的 super(參數) 代表調用父類的有參構造,具體調用哪個有參構造根據參數來決定
-
super(…)案例圖解
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-f8iRHAMy-1583144789620)(img/image-20200302143555121.png)]
-
this(…)用法演示
this(參數): 在本類的構造方法中調用本類的其他構造 public class Dog { int age; String name; public Dog() { //在本類的構造方法中 this(10,"來福"); //調用本類的另外一個構造 } public Dog(int age, String name) { this.age = age; this.name = name; } } 注意: this(參數)也必須寫在構造方法的第一行,所以this(參數)和super(參數)他們只能出現一個
-
小結
a.子類的構造方法中默認有一句super()調用父類無參構造,我們可以手動改寫super(參數)調用父類的有參構造, 具體是哪個有參構造,由參數決定 b.super(...)和this(...) 必須在第一行,所有不能同時出現 c.super(..)和this(..)調用父類的構造和子類自己的其他構造,具體哪個構造由參數決定 d.super(..) 調用父類的有參構造,初始化父類繼承的成員變量 e.this(..) 調用子類的其他構造方法
2.12 Java中繼承的特點
1. Java只支持單繼承,不支持多繼承。(一個類最多隻有一個親爹)
2. 一個類可以有多個子類。(一個類可以有多個孩子)
3. 可以多層繼承(一個類可以有父類,其父類也有父類)
總結: Java只支持單繼承,但是支持多層繼承
第三章 抽象類
3.1 抽象類的概念和引入
a.抽象方法: 只有方法的聲明,沒有方法的實現
b.含有抽象方法的類就是一個抽象類
3.2 abstract使用格式
-
抽象方法
public abstract 返回值類 方法名(參數列表);
-
抽象類
public abstract class 類名{ 抽象方法 正常方法 }
-
抽象類的使用
//抽象類:動物 public abstract class Animal { //抽象方法:跑 public abstract void run(); } 注意:抽象類是不能創建對象的,天生就是做父類的! 給其他子類繼承的!!! 抽象類不能創建對象,需要有子類繼承它,並且重寫所有抽象方法之後,該子類才能創建對象 //抽象類:動物 public abstract class Animal { //抽象方法:跑 public abstract void run(); } /** * 抽象類的子類貓 */ public class Cat extends Animal { //a.給Cat也加上abstract //b.重寫抽象類中所有的抽象方法 @Override public void run() { System.out.println("貓在屋頂上跑..."); } } public static void main(String[] args) { //1.創建Animal的對象 //Animal an = new Animal(); // Java規定抽象類不能創建對象 //2.創建Animal的子類Cat對象 Cat cc = new Cat(); cc.run(); }
3.3 抽象類的特徵和注意事項
抽象類的特徵:
有得有失!!
有得: 抽象類具備了含有抽象方法的能力
有失: 失去創建對象的能力
注意事項:
a.抽象類不能創建對象(Java規定的!!)
b.抽象類是有構造方法的,用於初始化類的成員變量
c.抽象類中不一定有抽象方法,但是含有抽象方法的類一定是抽象類(一般來說抽象類中是有抽象方法)
d.抽象類的子類必須重寫抽象類的所有抽象方法,否則子類還是一個抽象類
e.抽象類的天生作用就是做父類,爲子類提供模板
3.4 抽象類存在的意義
抽象類的天生作用就是做父類,爲子類提供模板
3.5 第一個設計模式:模板模式(司機開車)
司機開車:
開門,點火,開車,熄火,關門
新司機:
開門,點火,兩隻手全是汗緊握方向盤,熄火,關門
老司機:
開門,點火,一隻手接電話,一隻手抽着煙,偶爾手指點點,熄火,關門
/**
* 司機類,父類,模板
*/
public abstract class Driver {
//開車
public void drive(){
System.out.println("開門...");
System.out.println("點火...");
kai();
System.out.println("熄火...");
System.out.println("關門...");
}
////新司機: 兩隻手全是汗緊握方向盤
////老司機: 一隻手接電話,一隻手抽着煙,偶爾手指點點
public abstract void kai();
}
/**
* 新司機
*/
public class NewDriver extends Driver {
@Override
public void kai() {
System.out.println("兩隻手全是汗緊握方向盤,慢慢開車..");
}
}
/**
* 老司機
*/
public class OldDriver extends Driver {
@Override
public void kai() {
System.out.println("一隻手接電話,一隻手抽着煙,偶爾手指點點,biu一下過去了..");
}
}
//測試類
public class TestDemo {
public static void main(String[] args) {
//1.新司機
NewDriver nd = new NewDriver();
nd.drive();
//2.老司機
OldDriver od = new OldDriver();
od.drive();
}
}
總結
繼承:
a.繼承的格式
public class 子類 extends 父類{
}
b.不能繼承的內容
i.構造方法子類不能繼承
ii.私有成員子類可以繼承但是不能直接使用(間接使用,通過get/set方法使用)
c.繼承後成員變量和成員方法的特點:
i.不同名,沒有歧義
ii.同名時在子類中優先調用子類自己的成員
iii.我們可以使用關鍵字
super.變量名 訪問父類的同名成員變量
super.方法名() 調用父類的同名成員方法
d.方法的重寫
方法的重寫:在繼承關係中,子類有一個和父類除了方法體其他一模一樣的方法,該方法稱爲重寫的方法
什麼時候需要重寫:
當子類繼承父類的方法後,發現父類的方法適用,那麼子類就可以重寫該方法
重寫時可以使用@override幫助我們檢測是否重寫格式正確
e.super(..)
用於子類的構造方法第一行,調用父類的構造方法,具體是哪一個構造
由super(參數)中的參數決定
f.this(..)
用於本類的構造方法第一行,調用本類的其他構造方法,具體是哪一個構造
由this(...)中的參數決定
g.Java繼承的特點:
只支持單繼承,但是支持多層繼承
抽象類:
a.抽象方法格式: public abstract void 方法();
抽象類格式: public abstract class 抽象類名{ 可能有抽象方法,也可以沒有抽象方法}
b.抽象類怎麼用?
使用子類繼承抽象類,重寫所有抽象方法後,子類才能創建對象
c.抽象類的意義:
給子類繼承的,爲子類提供的模板(模板設計模式)