《Hack與HHVM權威指南》——1.5.2覆蓋方法的型別

華章計算機發表於2017-05-02

本節書摘來自華章出版社《Hack與HHVM權威指南》一書中的第1章,第1.5.2節,作者 Owen Yamauchi,更多章節內容可以訪問雲棲社群“華章計算機”公眾號檢視。

1.5.2 覆蓋方法的型別

在Hack的程式碼之間,繼承是更加複雜的相互關係中的一種。這複雜性主要來自於當繼承關係被建立時,繼承和被繼承的程式碼之間的分離現象。舉例來說,如果你有個型別標註為SomeClass的物件並可以呼叫這個物件的某個方法,那麼你可以呼叫繼承自SomeClass的任何類的某個方法。這個呼叫仍然需要是型別安全的,這就意味著覆蓋其他方法的時候,方法的型別必須有一定的規則。
在一個覆蓋方法中,引數型別必須和被覆蓋的方法型別完全一致。這主要是因為繼承自PHP的一個行為。在PHP中,任何覆蓋自抽象方法或者介面中宣告的覆蓋方法,都必須精確地匹配被覆蓋方法的引數型別。這在未來Hack版本中的宣告可能會有所改變,允許改變方法的引數型別將是更通常的做法。
換句話說,當進行方法覆蓋時,覆蓋方法的返回型別並不一定保持相同,相對於被覆蓋的方法而言,覆蓋方法可以有一個更加明確的返回型別。例如:

class ParentClass {
  public function generate(): num {
    // ...
  } 
}
class ChildClass extends ParentClass {
  public function generate(): int {  // OK
    // ...
  } 
}

雖然改變了返回型別,這種多型的呼叫仍然是型別安全的。
function f(ParentClass $obj) {
$number = $obj->generate();
// 即使$obj是個ChildClass例項,generate()方法自然會返回num型別
// 因為ChildClass::generate() 返回的是int型別,而所有int型別都屬於num型別
用更通常的返回型別進行覆蓋是非法的。例如,如果ChildClass的generate()方法被宣告成返回型別為mixed的話,型別檢查器將會報告錯誤。


相關文章