物件貼近現實生活的樣貌
為甚麼要有物件導向 ?
用 funct 的寫法,code 會很分散,因為最後還是要依靠各個 funct,但各個 funct 其實是散落在不同地方。以計算機小程式為例
如果還有其他功能,相同類型的 funct 可能就會被打散。code 散落各地但最後 call 一個 funct 做這些事情。
此外,沒有物件全部用陣列表達會變得非常麻煩,會變得像是一個一個變數分散開來。但有了物件,就可以將相關的屬性集合起來。
sum up
為甚麼要有物件導向
- 因為純用 funct,code 會散落各地
- 物件可以將相關屬性集合起來
# 重要觀念
## 設計圖:class (類別)
定義物件的長相,有什麼樣的內容,有什麼樣的 funct 可以使用
基本上在 class 裡面的 funct 我們稱呼為 method(方法)
透過 new 出一個 instance 將設計圖變成實體,然後存到變數 $dog 去。有了真的狗後就可以執行一些方法。
$dog 是 Dog 的實體。
因為 php 裡面 dot (.) 是做字串連接,所以要改成箭頭。
funct 前面還有不同的關鍵字,可以把它想成宣告方法,預設為 public,表示在哪裡都可以存取的到這個方法。
若改成 private,外面就沒辦法呼叫。所以為甚麼要寫一個外面沒辦法呼叫的 funct ? 這的東西我們叫他封裝
封裝 Encapsulation
將細節都藏到 class 裡面,那開出去外面的東西長相就會相對簡單。ie 將細節都隱藏到物件裡面,外面不需要知道這些細節只要 call 他就好了
首先,將 hello 設為 public funct,所以在外面就可以用 $a->hello();
,但如果想在外面呼叫 $a->getHelloSentence();
是無法得,因為他是 private
ie 開一個方法出去叫 hello,如果想要這個狗打招呼只要 call $a->hello();
,你完全不需要知道他的底層如何實作。只要用,不需要知道細節,這就叫封裝。
$this 指的是現在狗的這個實體。
ex1
宣告一個變數,先加 private,ie 外面無法存取
如果將變數改成 public,外面可以正常存取
會輸出 I am leo
當我們將 $a->name = 'leo'
註解,會輸出 I am default
可以經由 public 的變數在外面改這些東西
若在裡面要存取自己的東西,就用 $this, $this 表示我現在的 instance,我輸出的是我現在 instance 的 name
一個設計圖可以產生多個東西,一個 class 可以產生出多個 instance,每個 instance 都有它自己的資料。
ex2
通常不會將東西設為 public,因為所有人都可以進行修改。
透過 setter funct,去專門設定變數
透過 getter 將我的東西吐回去
東西改成 public 外面也可以存取,為何要這麼麻煩 ?
第一、不想讓東西無意間被改動,只希望他透過這兩個 method 進行存取。getter, setter 可以做一些檢查,可以保證裡面東西不會被外面動到
Recall: AJAX request
瀏覽器提供 XMLHttpRequest 這個 class 給我用,因為需要製造出一個真的 request,所以需要 new 出一個 instance
此外,語意上更清楚、更好維護。
- 我要一個新的 request
- 要送到哪去
- 加一個 cb funct / 將 response 讀回來
- 將 request 送出
比起 sendRequest(method, url, callback)
ex3 - js 計算機
你要怎麼讓別人用這個東西著手,別人在麼 call 比較方便想。(與經驗值有關)
如果將 input 分成 inputNumber 與 inputOperator,還要讓去 call 的人決定是甚麼 type,比較麻煩
js 語法差別在沒有 funct 這些東西,也沒有 private / public 可以使用,他的支援其實相對沒這麼完整
初始化:constructor
通常在 new 一個物件出來時,我們會希望在初始化的同時傳一些資訊進去,ex: $a = new Dog('leo');
這樣狗一出來就不用呼叫 setter funct。透過 constructor 進行接收,php 裡面會用兩個底線開頭
用 new 來 call funct,會執行到 __construct
,然後就可以設定一些東西
ex:
把東西都集中在 DB 這個 class 裡面,所以要改任何相關的東西就去這裡面改就好了,透過集中管理讓 code 更好維護
有 construct 也有 destruct。當物件要關掉,要做甚麼善後的事情
QA
Object 與 instance 的差別 ? 可以把 object 想成一個 instance,new 出的 instance 就是一個物件,他是這個 class 的 instance。
有物件導向才有 this
this 指的是那個實體本身。
為甚麼需要 this ? 因為需要一個東西可以指到現在自己的 instance。this 通常會發生在 funct 裡面。
funct 一定要傳參數,才會知道要對甚麼東西做操作。但用物件導向,我們將 funct 變成只要傳一個參數就好了,傳她真正需要的參數。
因為我們將東西藏在裡面,裡面可以用 this 指射到我們現在指射到的這個 instance 這個物件,他的 conn 這個變數,就不需要顯示 ie 你沒有傳她會不知道要對甚麼東西做甚麼事情。有了 this 可以指射到我現在這個 conn
$conn->fetch_result($query)
function fetch_result($q) {
$this->conn->mysql_fetch_result($q);
}
js 不是 new 出來的東西也有 this 可以用。所以他到底指向誰 ?
ex js 計算機
加上 eval 就會把我們裡面輸出的東西當作程式碼,eval(this.text)
示意:
繼承(Inheritance)
狗是動物,所以現在有 class 叫 animal,裡面就有 hello 這個方法。我們假設所有動物都會說話。
動物有的這些方法與屬性,狗也應該要有。因為狗也是一種動物。
繼承會繼承某個 class 裡面的所有東西。
但如果在狗有繼承的東東,就會出現覆寫
另外,this 在他底下全是共通的
如果上層用 private 會發生甚麼事情嗎 ? 他就只能給他自己存取,我在 Dog 找不到 this.name 這個東西,因為宣告 private 所以只有 Animal 能存取這個屬性
關鍵字除了 public, private 還有 protected,其中 protected 很像 private 只是繼承他的東西也可以使用,但仍然無法直接在外面使用,ie 從自己與其子孫看是 public,但從外面看是 private
php 透過 patent::
可以存取到 parent 的方法,ex: 我的 parent 的 sayHello
js 透過 super
存取到 parent 的方法,ex: 輸入是三,但我讓他到 parent 是 3。對 input 這個 method 做小的改變
如果想改其中一小部分 code,就可以用繼承做這件事,保持他原有的特性又新加上一些東西
靜態方法:static
宣告 class 後需要 new 一個 instance 才能使用它裡面的這些 method。
加上 static 的關鍵字呼叫也可以
static 是說這個 method 他不是屬於 instance,他是屬於這個 class 的。所以比起下面黃色線的呼叫,他其實會 Dog::test()
要存取 class 會用冒號,箭頭 -> 是給 instance 用
class 本身也可以有一些 funct
靜態方法的好處是你這個東西他不會改變,他是建立在 class 底下而非 instance 底下。通常不會有甚麼資訊。有靜態 funct,也有靜態變數。
通常會存一些不會改到的資料,每個 instance 都會共用到的變數,就會宣告成 static,因為他不需要改。
ex1: call api
有沒有東西是不該放在 instance 裡面,而應該放在 class 裡面的呢 ?
第一種:靜態變數綁在 class 上面,這個變數永遠就只有一份。因為他是跟 class 走的
第二種:將變數放在 instance 裡面,不同的 instance 不同的記憶體位置
ex2: time zone
如果不合理,你已經 new 了也有點怪
希望在 new 之前就先檢查過
JS 的 class 與 prototype
js 裡面沒有 class 這個關鍵字,他沒有 class 語法。可以使用是因為底層用其他東西實做
js 希望還是能維持這樣的語法,如果 Calculator 不是 class 他可以是甚麼 ? 他可以是 funct,用 new 呼叫這個 funct,這個 funct 就變成建構子的作用
兩邊是一樣的,只是有了 class 之後會有一個叫做 constructor 的 funct
js 希望可以用 instance 的方法,是跟其他物件導向語言差不多的。他透過 funct 去實作。所以當我用 new 接一個 funct 的時候,他回傳出來的 calculator 就是 Calculator 這個 funct 或說是這個 class 的 instance
如果要加一些 method 的話,他會透過 prototype 的寫法