kphp icon indicating copy to clipboard operation
kphp copied to clipboard

@kphp-template and instance_cast($object, T:class)

Open comm644 opened this issue 2 years ago • 0 comments

Цель изменения:
если получаем шаблонный тип T , то все его использования должны подставиться на тип реализации шаблона. Это ускорит исполнение работы с коллекциями целевого типа, а не интерфейсного при распаковке из внешних источников при котором надо проверять соответствие типу в каждом применении или повторно создавать коллекцию.

пример:

/**
 * @param $proto
 * @return object
 * @kphp-template T $proto
 * @kphp-return T
 */
public function get(object $proto) : T
{
  return instance_cast($this->object, T::class);
}
$instanceA = $holder->get(new A);
$instanceB = $holder->get(new B)

ожидание: создана функция по шаблону, если получаем шаблонный тип T , то все его использования должны подставиться на тип реализации шаблона

class_instance<C$A> f$Holder$$get$A(class_instance<C$Holder> const &v$this, class_instance<C$A> const &v$proto) noexcept  {
//62: {
//63: return instance_cast($this->object, T::class);
  return f$instance_cast< class_instance<C$A> >(v$this->$object, v$const_string$a_key);
}

сейчас по факту: 1 . результат не раскрылся 2. подстановка для instance_cast

не раскрылась

//source = [testTemplate.php]
//61: public function get(object $proto) : T
class_instance<C$T> f$Holder$$get$A(class_instance<C$Holder> const &v$this, class_instance<C$A> const &v$proto) noexcept  {
//62: {
//63: return instance_cast($this->object, T::class);
  return f$instance_cast< class_instance<C$T> >(v$this->$object, v$const_string$usf7aa15be8a7d743e);
}

Практическое применение:

/**
 * @param Holder $holder
 * @param object $class
 * @param $docs
 * @return array
 * @kphp-template T $class
 * @kphp-return   T[]
 */
function createArray(Holder $holder, $class): array
{
  $docs = [new T]; //try to create T[]
  for ($i = 0; $i < 10; ++$i) {
    $docs[] = instance_cast(clone $holder->object, T::class);
  }
  return $docs;
}

$arrayA =  createArray($holder, new A); // expect result A[]
$arrayB =  createArray($holder, new B); // expect result A[]

полный код теста


class T{}
interface I{  }
class A implements I { 	function methodA(){ echo "A";	} }
class B implements I { 	function methodB(){ echo "B"; } }

class Holder
{
	public I $object;

	/**
	 * Holder constructor.
	 * @param I $object
	 * @kphp-template I $object
	 */
	public function __construct( $object)
	{
		$this->object = $object;
	}

	/**
	 * @param object $object
	 * @kphp-template $object
	 * @return Holder
	 */
	public static function create(object $object)
	{
		return new Holder($object);
	}
	/**
	 * @param $proto
	 * @return object
	 * @kphp-template T $proto
	 * @kphp-return T
	 */
	public function get(object $proto)
	{
		return instance_cast($this->object, T::class);
	}
}

$holderA = Holder::create(new A());
$holderB = Holder::create(new B());

/** @var A $varA */
$varA = $holderA->get(new A);
$varA->methodA();


/** @var B $varB */
$varB = $holderB->get(new B);
$varB->methodB();


/**
 * @param Holder $holder
 * @param object $class
 * @param $docs
 * @return array
 * @kphp-template T $class
 * @kphp-return   T[]
 */
function fillWithCast(Holder $holder, $class): array
{
	$docs = [$class];
	for ($i = 0; $i < 10; ++$i) {
		$docs[] = instance_cast(clone $holder->object, T::class);
	}
	return $docs;
}


/** @var A[] $arrayA */
$arrayA = [];
$arrayA = fillWithCast(new Holder(new A), new A);
$arrayA[0]->methodA();

/** @var B[] $arrayB */
$arrayB = [];
$arrayB = fillWithCast(new Holder(new B), new B);
$arrayB[0]->methodB();




comm644 avatar Oct 25 '21 10:10 comm644