Тип 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, и в результате получается:
Исправляемая фатальная ошибка: ошибка типа взлома: неверное назначение
Единственное решение, работающее в этом случае, это вообще не определять тип. Есть ли какой-то трюк для определения универсального объекта?
1 ответ
Универсальный тип в Hack - это то, что вы получаете, когда опускаете аннотацию типа; это совместимо со всем. object
тип, известный проверщику типов, и поэтому предполагается, что у вас есть class object
где-то.
Соединение является объектом и может быть экземпляром Memcached, MySQLi и т. Д. Или NULL.
Правильный способ сделать это - определить интерфейс, который реализуют оба этих объекта, и использовать этот интерфейс в качестве типа здесь.
Наличие универсального типа объекта не дает информации для проверки типов; он до сих пор не знает, какие методы допустимы для вызова этого объекта. Интерфейс предоставляет типографской информации эту информацию.
Обратите внимание, что "какие методы безопасно вызывать, когда" - это то, что неявно кодифицировано в вашем приложении - код знает через некоторые внешние средства, когда безопасно вызывать определенные методы для Memcached, MySQLi и т. Д., Иначе ваш код не будет работать! Система типов Хака и системы типов в целом просто заставляют вас сделать это явным.
Кроме того, вы действительно не должны получать ваши ошибки типа как заразные фаталы от HHVM; это последний вид проверки. Попробуйте запустить hh_client
напрямую, возможно, даже показывает результат в вашей IDE; это даст вам гораздо более быстрый цикл итерации и намного больше информации, чем предоставляет HHVM.