Дано: hhvm + код на Hack + //strict mode
Требуется: реализовать паттерн "фабрика"
<?hh // strict
namespace mynamespace\Uri;
abstract class UriAbstract
{
protected string $_scheme = '';
public static function factory(string $uri = 'http') : this {
$aUri = explode(':', $uri, 2);
$scheme = (string)strtolower($aUri[0]);
if ( strlen($scheme) === 0 ) {
// throw Exception
}
if ( ctype_alnum($scheme) === false ) {
// throw Exception
}
switch ($scheme) {
case 'http':
case 'https':
$schemeHandler = new Http(); // Корень проблемы
break;
default:
throw new \Exception('Undefined scheme.');
}
return $schemeHandler;
}
}
// --------------
namespace mynamespace\Uri;
class Http extends UriAbstract {};
Суть вопроса в том, что фабричный метод UriAbstract::factory должен возвращать одного из потомков UriAbstract, например Http, Https или любого другого.
Проблема в том, что в strict mode необходимо указать тип возвращаемых методом данных, но в этом случае "this" - не корректный тип, т.к. он соответствует UriAbstract, а не возвращаемому Http.
Динамическое создание объекта класса через meth_caller ( string $class_name , string $method_name ), т.е. через статический метод а-ля Http::getInstance() тоже не сработает, т.к. $class_name должен быть "ValidClass::class".
Меня устроил бы вариант, приведенный в примере (сводящийся по сути к return new Http();), но что тогда написать вместо this в качестве возвращаемого значения?