c)constructors
1.全部都要執行
2.順序上==>下(父==>子)
3.super(引數):sup
d)overloading
●實作
UML
程式
(一)假設A沒有建構式,但school有建構式,compiler會出現錯誤訊息
=>required: String,int
=>因為在new A的時候,會run school的constructor,這時會需要引數,可是A沒有丟給school引數
做法:
引數透過子類別的建構式丟給父類別,如果沒有這樣做就不能繼承
A.java
//這個步驟是先接收user key的內容(接收外部資料)
A(String name,int chi){
//透過super(引數)才會把引數丟給父類別
super(name,chi);
System.out.println("A班學生");
}
=>注意!!super()中的順序和類型都要和父類別的建構式引數一致
=>在new的時候會先new A(所以引數就放在new A()),可是run是先run school(父類別)
school.java
class school{
String name;
int chi;
school(String name,int chi){
this.name=name;
this.chi=chi;
System.out.println("新增一位學生school\tname:"+name+"\tchi:"+chi);
}
}
*但如果交換System.out.println("A班學生");和super(name,chi);的順序,
compiler會出現次錯誤
=>super要放第一個,因為交換以後,變成先執行子類別在執行父類別的建構式了...
A.java
A(String name,int chi){
System.out.println("A班學生");
super(name,chi);
}
*如果A本身的建構式中也要放入引數
A.java
private int word;
//可以直接放在A()中,這邊的內容不用和school()中的內容一致,只要有包含school()中的內容即可
A(String name,int chi,int word){
//重點在super()中的內容要和school()中的內容一樣
super(name,chi);
this.word=word; //要記得放在super()後面
System.out.println("A班學生\t word:"+word);
}
add.java
A a=new A("maggie",80,95);
(二)overloading
假設school有多個建構式(有引數的建構式才會有多個)
school.java
String name;
int chi;
school(String name,int chi){
this.name=name;
this.chi=chi;
System.out.println("新增一位學生school\tname:"+name+"\tchi:"+chi);
}
school(String name){
this.name=name;
System.out.println("新增一位學生school\tname:"+name);
}
*A在繼承時,只需要選一個繼承即可,由super()中的引數判斷是繼承哪一個,但如果兩個都要繼承時,不可以在同一個建構式中寫兩個super(),因super()在同一個建構式中只能使用一次,全部都要繼承,子類別就要拆成好幾個建構式(至少一定要繼承一個)
A(String name,int chi,int word){
super(name,chi);
this.word=word;
System.out.println("A班學生\t word:"+word);
}
A(String name,int word){
super(name);
this.word=word;
System.out.println("A班學生\t word:"+word);
}
(三)A,A_1,和B都繼承
**繼承class之前一定要記得先去看class中的建構式
school.java
class school{
String name;
int chi;
school(String name,int chi){
this.name=name;
this.chi=chi;
System.out.println("新增一位學生school\tname:"+name+"\tchi:"+chi);
}
school(String name){
this.name=name;
System.out.println("新增一位學生school\tname:"+name);
}
}
A.java
class A extends school{
private int word;
A(String name,int chi,int word){
super(name,chi);
this.word=word;
System.out.println("A班學生\t word:"+word);
}
A(String name,int word){
super(name);
this.word=word;
System.out.println("A班學生\t word:"+word);
}
}
A_1.java
class A_1 extends A{
private int access;
A_1(String name,int chi,int word,int access){
super(name,chi,word);
this.access=access;
System.out.println("A_1組\taccess:"+access);
}
}
=>A_1有兩層要繼承又都有overloading時,只要處理他的上一層(A)建構式,因為school那一層已經由他的父類別(A)處理好了
B.java
class B extends school{
private int excel;
B(String name,int chi,int excel){
super(name,chi);
this.excel=excel;
System.out.println("B班學生\t excel:"+excel);
}
}
add.java
class add {
public static void main(String args[]){
A_1 a1=new A_1("maggie",80,95,60);
}
}
(6)methods方法
1.hsa-a
引用上例:
school加上show()method,A、B、A_1不變
void show(){
System.out.println("school學生");
}
去執行時,三個都有繼承show()
A a=new A("maggie",80,95);
a.show();
=>輸出school學生
A_1 a1=new A_1("maggie",80,95,60);
a1.show();
=>輸出school學生
B b=new B("maggie",80,77);
b.show();
=>輸出school學生
**當在做a1.show()時順序是,會先去A_1show()找,再去找Ashow(),最後在school找到show()
2.overloading
=>名字一樣,引數不一樣
=>上述在同一個class中的overloading規則也適用於父類別和子類別的關係(適用於上下關係)
當school有overloading且A本身又有自己的method=>這樣也適用overloading的規則
school.java
void show(){
System.out.println("school學生");
}
void show(String name){
System.out.println("school學生 姓名:"+name);
}
A.java
void show(int word){
this.word=word;
System.out.println("A班學生\t word:"+word);
}
在執行時
add.java
school s=new school("maggie");
s.show("kelly");
s.show(85);=>compiler會出現錯誤訊息,因為在查reference只會往上找不會往下找
A a=new A("maggie",80,95);
a.show(); //繼承school method
a.show("kent"); //繼承school method
a.show(58); //自己本身的method
3.override(改寫)
=>名字一樣,引數一樣,類型一樣
=>必須位於不同class(父,子),如果同一個class compiler就會出錯
當school有一個show(),A下面也有一個show(),名字類型和引數都一樣
school.java
void show(){
System.out.println("school學生");
}
A.java
void show(){
System.out.println("A");
}
add.java
school s=new school("maggie");
s.show();
System.out.println("=====");
A a=new A("maggie",80,95);
a.show();
=>執行時,s.show()是去抓school class的show(),A.show()是去抓A class的show()
**通常發現程式有錯時,作法有兩種
1.找原始碼去改school class中的show()
2.拿不到原始碼,或是不想改變已固定使用的介面,想做微調就好
=>在子類別用overriede的方式來改,可以避免其他繼承同一父類別的子類別被想到
傳值類method
在school中新增一傳值類methodd
school.java
int abc(int x){
// 把abc(int x)視為一個變數,return就是"="=>int abc(...)=x的意思
return x;
}
如果要改為輸入值+20,而且要從子類別A做調整:
(一)若改為如下
A.java
void abc(int x){ }
=>會出現錯誤訊息,類別不正確,因為當子類別方法的名字和引數都跟父類別相同時,就會自動當作override,就會去檢查類別
(二)正確做法
A.java
int abc(int x){
return x+20;
}
**如果superclass的方法有設定封裝權限(權限大小順序:public>protected>default>private)
=>子類別權限要>=父類別
=>如果沒有寫封裝權限就是default
=>只要沒有加private都可以繼承
如果在school中的int abc()封裝權限為protected,在A中的abc()為default
school.java
protected int abc(int x){
return x;
}
A.java
int abc(int x){
return x+20;
}
=>compiler會出現錯誤訊息,A class的封裝權限weaker than school class,
所以要把權限改為protected(相等)或public(大於)school才可以override
A.java
public int abc(int x){
return x+200;
}
5.內容
=>super.方法
如果要把繼承於父類別的函數拿去運算出另一個結果
school.java
protected int abc(int x){
return 3*x+100;
}
A.java
public int abc(int x){
return abc(x)+200;
}
=>abc(x)代表superclass的method,x還是帶int x
=>如果直接去執行,會出現一直在跑下列訊息,因為override,造成執行時去找到的是A class本身的abc(),一直呼叫自己造成遞迴(會有stackoverflow 記憶體不斷堆疊的問題)
正確做法
當名稱引數都一樣,又要引用上一層同樣的method時,就要用super.method,才不會因為被override造成遞迴的問題但只能引用上一層,上上一層不能引用,void不能這樣用,因為void不能當作值去做運算
A.java
public int abc(int x){
return super.abc(x)+200;
}
● Polymorphism 多型(=>用來討論方法的使用)
1)多個class,有共同的父類別
2)使用父類別定義物件名稱=>"new"新增物件(實體化)使用子類別
3)目的:會限制使用的"方法"數量
=>只有定義物件的父類別有定義的方法"名稱"才可使用
=>繼承或"override"
語法:
父類別 物件=new 子類別(); =>父類別和子類別間須有繼承關係
程式說明
(一)多型的宣告方式
原本new一個物件的方法如下:
add.java
A a = new A();
B b = new B();
C c = new C();
a.show();
b.show();
c.show()
*但因為ABC有共同的父類別,可以把左邊改為student,但左右兩邊一定要有繼承關係
add.java
student a = new A();
student b = new B();
student c = new C();
*如果這時我們要用a呼叫abc():
add.java
student a = new A();
student b = new B();
student c = new C();
a.abc();
student.java
void show(){
System.out.println("hello student");
}
A.java
void show(){
System.out.println("hello student a");
}
void abc(){
System.out.println("hello student a, abc");
}
=>compiler時會出現錯誤訊息,因為在做a.abc時,call by reference會先去看左邊的student class是否有abc(),結果student中並沒有abc()method
(二)想使用子類別的某個方法但父類別沒有時的作法
studetn.java
void show(){
System.out.println("hello student");
}
B.java
void abc2(){
System.out.println("hello student b ,abc2");
}
add.java
student a = new A();
student b = new B();
student c = new C();
a.abc();
b.abc2();
=>因為在sudent中並沒有abc2()這個方法,所以編譯時在call by reference這個階段時就出現錯誤了
=>如果在使用多型時,父類別沒有的方法,是絕對不能用的,如果一定要用某個子類別有但父類別沒有的方法,就要在父類別中加入該方法但不用寫內容(因為只是要用來被子類別的內容override)
=>故此例要在student中加入void abc2(){}
**所以多型的使用又稱為異質宣告,和一般宣告最大的不同,在於方法的限制比較嚴格,只有兩種做法
1.由父類別繼承而來
2.override而來
=>須注意的是,當call by reference時,是由等號左邊開始找,所有方法都要在父類別找的到compiler才能過,等執行時卻是從等號右邊開始找class中有沒有該方,有override會先做,沒有override就做由父類別繼承而來的方法(因為執行的時候要看記憶體,只有new的時候才會有記憶體,所以執行時從右邊開始找)
**所以多型的父類別有索引目錄的概念,個別的子類別都會有父類別所列的方法,然後各自有不同的功能
(三)多型的method繼承與method override的實作
*在student和A中都有abc(),但在B和C中都沒abc()
student.java
void abc(){
System.out.println("hello student 繼承來的");
}
A.java
void abc(){
System.out.println("hello student override");
}
add.java
student a = new A();
student b = new B();
student c = new C();
a.abc();
b.abc();
c.abc();
outputs
hello student override
hello student 繼承來的
hello student 繼承來的
*如果A下面還有A_1,因為也有共同父類別student,所以也能用多型的規則來new,但是當呼叫abc()method時,因為上一層A有abc()method,會直接用A的
add.java
student a = new A();
student b = new B();
student c = new C();
student a_1=new A_1();
a.abc();
b.abc();
c.abc();
a_1.abc();
outputs
hello student override
hello student 繼承來的
hello student 繼承來的
hello student override
4)搭配=>陣列使用(因為資料量很多,用來管理名字)
=>多型就是為了搭配陣列以及和後續會提到的抽象類別、interface有關
假設A班有2人B班有2人C班有一人,隨機輸入資料
student.java
void abc(){
System.out.println("hello student");
}
A.java
void abc(){
System.out.println("hello student a");
}
B.java
void abc(){
System.out.println("hello student b");
}
C.java
void abc(){
System.out.println("hello student c");
}
add.java
student [] s={
new A(),
new B(),
new A(),
new C(),
new B()
};
for(int i=0;i<s.length;i++){
s[i].show();
}
//outputs
文章標籤
全站熱搜

muchone教得太好了! 忍不住給個讚! 重點又精準. 謝謝
謝謝,很高興文章對您有幫助