2015-08-15 37 views
0

比方說,我有靜態的連接器,允許不同的適配器的代理實例:HackLang類型不同的對象

$m = Connector::take('mcrouter'); 
$db = Connector::take('production_database'); 

連接器必須初始化和運行期間處理連接:

protected $connection; 
abstract protected function openConnection($config); 

某處內部適配器:

$this->connection = $this->openConnection($config); 

連接是一個對象,可能是Memcached,MySQLi的一個實例等等或NULL。 所以邏輯上我想這樣做:

protected ?object $connection; 
abstract protected function openConnection($config):?object; 

但在同一時間連接是不是真正的「對象」的情況下,它是memcached的實例,例如,其結果是:

Catchable fatal error: Hack type error: Invalid assignment

在這種情況下唯一的解決方案是根本不定義類型。 定義通用對象有一些技巧嗎?

回答

1

Hack中的通用類型是您在省略類型註釋時獲得的;它兼容一切。 object不是typechecker已知的類型,因此它假定您有某個class object

The connection is an object and could be an instance of Memcached, MySQLi etc. or NULL.

做到這一點,正確的方法是定義這兩個目標的實現一個接口,並使用該接口作爲這裏的類型。

擁有泛型對象類型不會給typechecker提供任何信息;它仍然不知道哪些方法有效地調用該對象。該界面給出了類型檢查器的信息。

請注意,「什麼時候可以安全調用的方法」是在您的應用程序中隱式編碼的內容 - 代碼通過某種外部手段知道何時可以安全地調用Memcached,MySQLi等的某些方法,否則您的代碼將不會不行! Hack的類型系統和類型系統,只是迫使你明確這一點。

另外,你真的不應該把你的類型錯誤作爲HHVM的可捕獲的致命錯誤;這是最後一種檢查。嘗試直接運行hh_client檢查器,甚至可能在IDE中顯示其結果;它會給你一個更快的迭代週期,以及比HHVM提供的更多信息。

+0

感謝您的詳細解答!我使用接口和抽象類,但是我意識到這種方法本身並不適合嚴格的打字,似乎是PHP的正常設計,而對於Hack來說則是糟糕的設計。我無法使用某些AdapterInterface擴展默認的Memcached類,只用於打開/關閉連接方法,與我無法執行「MemcachedAdapter擴展\ Memcached實現AdapterInterface」的方式相同,原因很多。方法名稱的截取,或者在這種情況下,我必須將Memcached和Mysql的方法結合在一個接口中,這是奇怪和糟糕的設計 –

相關問題