Тип 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.

Другие вопросы по тегам