假设我有静态连接器,允许代理不同适配器的实例:
$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的实例,结果是:
可捕获的致命错误:黑客类型错误:无效的分配
在这种情况下唯一的解决方案是根本不定义类型。 是否有一些定义通用对象的技巧?
答案 0 :(得分:1)
Hack中的通用类型是省略类型注释时获得的类型;它与一切兼容。 object
不是类型检查器已知的类型,因此假定您在某处有class object
。
连接是一个对象,可以是Memcached,MySQLi等的实例,也可以是NULL。
正确的方法是定义这两个对象实现的接口,并将该接口用作此处的类型。
拥有通用对象类型不会向类型检查器提供任何信息;它仍然不知道调用该对象的有效方法。界面为类型检查器提供了信息。
请注意“在您的应用程序中隐式编写的”可以安全调用的方法 - 代码通过某些外部方式知道何时可以安全地调用Memcached,MySQLi等的某些方法,否则您的代码将无法使用工作! Hack的类型系统和一般的类型系统只会迫使你明确这一点。
顺便说一句,你真的不应该把你的类型错误当作来自HHVM的可捕获的致命错误;这是最后的手段。尝试直接运行hh_client
检查程序,甚至可以在IDE中显示其结果;它将为您提供更快的迭代周期,以及比HHVM提供的更多信息。