摘要:難道,就沒有強類型特征答案是明確的,肯定有其實是一種強類型和弱類型的結合體。強類型語言中,編譯器通常提供編譯檢查錯誤的功能,它也是非常有用的。與此同時,強類型的代碼看起來也是很生硬的。
聲明:本文并非博主原創,而是來自對《Laravel 4 From Apprentice to Artisan》閱讀的翻譯和理解,當然也不是原汁原味的翻譯,能保證90%的原汁性,另外因為是理解翻譯,肯定會有錯誤的地方,歡迎指正。
歡迎轉載,轉載請注明出處,謝謝!
接口約定 強類型和弱類型Water Fowl 這里我不知道該怎么翻譯,按理解就將他翻譯成弱類型?
之前的文章中,涵蓋了依賴注入的基礎知識:什么是依賴注入;如何實現;以及他有什么好處。在舉例的代碼中,也展示了如何將接口注入到類之中。在我們繼續深入之前,有必要深入一下接口相關的內容,因為很多PHP開發人員對接口都有相當程度的不熟練。
在我成為一個PHP程序員之前,我是寫.NET的。難道我喜歡痛苦或者其他什么的么?在.NET中接口無處不在,事實上.NET框架的很多核心內容就是接口,還有一個好處:很多象.NET的語言如C#、VB等都是_強類型_的。通常,傳入方法的原生對象,必須預先定義好相關的_類型_。例如下面的C#代碼:
public int BillUser(User user) { this.biller.bill(user.GetId(), this.amount) }
我們不僅定義了傳入參數的_類型_,函數返回的類型都是已經定義好的。C#提倡_安全類型_。函數BillUser方法傳入的參數必須是User對象。
PHP是一種_弱類型_語言。在弱類型語言中,對象中可用的方法取決于其方法的使用形式,而非方法繼承或者實現的位置。例如:
public function billUser($user) { $this->biller->bill($user->getId(), $this->amount); }
我們無需告訴方法類型的參數是什么,我們可以傳入任意對象,只要他有getId方法就行。這就是弱類型編碼的例子。如果一個東西看起來象鴨子,叫聲也象,那么他就是一個鴨子。換言之,如果一個對象象user,行為也象user,那么他就是一個user對象。
難道,PHP就沒有強類型特征?答案是明確的,肯定有!PHP其實是一種強類型和弱類型的結合體。為了說明這一點,我們修改下上例的代碼:
public function billUser(User $user) { $this->biller->bill($user->getId(), $amount); }
在方法參數中,加入User約定后,就能確保傳入方法的參數必須是User的實例化對象或者是繼承自User的一個實例。
兩種類型各有優劣。強類型語言中,編譯器通常提供編譯檢查錯誤的功能,它也是非常有用的。方法的輸入和輸出都是明確的。
與此同時,強類型的代碼看起來也是很生硬的。比如Eluquent ORM中提供的動態方法whereEmailOrName就不能象C#那樣明確參數和返回值的類型。這里不討論孰優孰劣,我們各取所長,但是,不假思索的死認某一種方式肯定會埋下很多坑。
示例接口就是約定,他不包含具體的代碼實現,而定義了對象需要實現的一系列的方法。如果一個對象實現了某個接口,那么這個接口的方法肯定都能在這個實例對象中使用。通過約定固化了某些方法的實現,這種_多態_就能保證語言的類型安全。
什么是多態?
多態含義很廣,可以理解為一種實體的多種形式。在本書中,我們指代接口的多種實現方式。例如:UserRepositoryInterface可以有MySQL和Redis兩種存儲實現方式,但是每一種都是UserRepositoryInter接口的實現。
為了說明強類型在接口中的靈活和重要性,我們來實現如下一個酒店預訂的例子:
interface ProviderInterface { public function getLowestPrice($location); public function book($location); }
當用戶預訂房間是,我們想將此事件記錄到系統中。我們在User類中添加如下方法:
class User { public function bookLocation(ProviderInterface $provider, $location) { $amountCharged = $provider->book($location); $this->logBookedLocation($location, $amountCharged); } }
我們限定了參數$provider的類型,User類中就能假定book方法是可安全調用的,這就使得bookLocation有較強的操作性,我們不用關心酒店是如何實現房間預訂這一過程。下面的代碼就能體現這一特性:
$location = "Hilton, Dallas"; $cheapestProvider = $this->findCheapest($location, array( new PricelineProvider, new OrbitzProvider, )); $user->bookLocation($cheapestProvider, $location);
贊!我們不用關心那家酒店最便宜,只需要將他傳入User實例中就能成功預訂房間。因為User對象要求傳入的參數是繼承自ProviderInterface的對象,未來添加更多的酒店提供商,都能使我們的代碼穩定的運行。
接口和團隊開發忘掉細節
記住,接口_不實現_任何細節,只是簡單的定義類必須實現的方法。
當團隊構建大型應用時,不同的模塊進程是不同的。比如,有人處理數據層,有人處理前端web、控制器層。前端開發項測試自己的控制器,但是后端人員開發進度緩慢。但是,如果我們能約定好接口,后端人員只須遵循接口定義:
interface OrderRepositoryInterface { public function getMostRecent(User $user); }
一旦約定了接口,前端開發人員,在代碼沒有實現的情況下,也能測試自己的控制器!這樣整個應用中就不用擔心不同模塊的開發進度,也不會影響到正常的測試用例的編寫。更深一點來說,這種方法不會影響到其他組件的開發,做到了無知是福。我們不需要讓我們的類必須知道其他類是_怎么_實現的,只需要知道他_能夠_干什么。現在,我們已經定義了接口,那么我們可以繼續我們控制器代碼的實現了:
class OrderController { public function __construct(OrderRepositoryInterface $orders) { $this->orders = $orders; } public function getRecent() { $recent = $this->orders->getMostRecent(Auth::user()); return View::make("orders.recent", compact("recent")); } }
前端開發人員可以自己實現一個“假”接口,來測試應用試圖中需要填充的數據。
class DummyOrderRepository implements OrderRepositoryInterface { public function getMostRecent(User $user) { return array("Order 1", "Order 2", "Order 3"); } }
接口實現之后,我們就能將其綁定到容器中,就能在整個應用中使用他了:
App::bind("OrderRepositoryInterface", "DummyOrderRepository");
當后端開發人員實現了他的模塊,比如:RedisOrderRepository。我們再次通過修改綁定將其應用到項目之中。
接口大綱
接口在被用來定義項目“骨架”上是非常有用的。在項目組件設計階段可以促進團隊間設計討論。比如定義BillingNotifierInterface接口,并討論接口相應的方法,在敲代碼前就能用接口定義出一套好的API。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/22952.html
摘要:然而,我們需要注意的是僅是軟件設計模式依賴注入的一種便利的實現形式。容器本身不是依賴注入的必要條件,在框架他只是讓其變得更加簡便。首先,讓我們探索下為什么依賴注入是有益的。繼續深入讓我們通過另一個示例來加深對依賴注入的理解。 聲明:本文并非博主原創,而是來自對《Laravel 4 From Apprentice to Artisan》閱讀的翻譯和理解,當然也不是原汁原味的翻譯,能保證9...
摘要:實際上,本原則要求接口必須是粒度明確的。當你的代碼不符合接口分離原則時,那也肯定違背了單一責任原則。接口分離原則本原則是指在實現類中對于接口中的方法并不強制去實現使用不到的方法。 聲明:本文并非博主原創,而是來自對《Laravel 4 From Apprentice to Artisan》閱讀的翻譯和理解,當然也不是原汁原味的翻譯,能保證90%的原汁性,另外因為是理解翻譯,肯定會有錯誤...
摘要:控制反轉容器控制反轉使依賴注入變得更加便捷。有瑕疵控制反轉容器是實現的控制翻轉容器的一種替代方案。容器的獨立使用即使沒有使用框架,我們仍然可以在項目中使用安裝組件來使用的控制反轉容器。在沒有給定任何信息的情況下,容器是無法實例化相關依賴的。 聲明:本文并非博主原創,而是來自對《Laravel 4 From Apprentice to Artisan》閱讀的翻譯和理解,當然也不是原汁原味...
摘要:組件擴展通常有兩種方法向容器中綁定自己的接口實現痛過使用工廠模式實現的類注冊自己的擴展。類庫管理類以工廠模式實現,負責諸如緩存等驅動的實例化。閉包須要傳入繼承自和容器的實例化對象。當完成擴展之后要記住中替換成自己的擴展名稱。 聲明:本文并非博主原創,而是來自對《Laravel 4 From Apprentice to Artisan》閱讀的翻譯和理解,當然也不是原汁原味的翻譯,能保證9...
摘要:在改變存儲系統的情況下,必須對進行修改,違背了開放封閉原則。傳統的依賴痛過倒置就能事代碼變得非常靈活,易于改變 聲明:本文并非博主原創,而是來自對《Laravel 4 From Apprentice to Artisan》閱讀的翻譯和理解,當然也不是原汁原味的翻譯,能保證90%的原汁性,另外因為是理解翻譯,肯定會有錯誤的地方,歡迎指正。 歡迎轉載,轉載請注明出處,謝謝! 依賴反轉原則 ...
閱讀 3197·2021-11-08 13:18
閱讀 1353·2021-10-09 09:57
閱讀 1182·2021-09-22 15:33
閱讀 3960·2021-08-17 10:12
閱讀 5053·2021-08-16 11:02
閱讀 2676·2019-08-30 10:56
閱讀 962·2019-08-29 18:31
閱讀 3251·2019-08-29 16:30