如何指示一个参数;包括特质“;在PHPDoc
最近,我在使用PhpStorm实现PHP应用程序时遇到了一个有趣的情况。下面的代码片段说明了该问题如何指示一个参数;包括特质“;在PHPDoc,php,phpstorm,phpdoc,Php,Phpstorm,Phpdoc,最近,我在使用PhpStorm实现PHP应用程序时遇到了一个有趣的情况。下面的代码片段说明了该问题 interface I{ function foo(); } trait T{ /** * @return string */ public function getTraitMsg() { return "I am a trait";
interface I{
function foo();
}
trait T{
/**
* @return string
*/
public function getTraitMsg()
{
return "I am a trait";
}
}
class A implements I{
use T;
function foo(){}
}
class C implements I{
use T;
function foo(){}
}
class B {
/**
* @param I $input <===Is there anyway to specify that $input use T?
*/
public function doSomethingCool($input){ //An instance of "A" or "C"
$msg = $input -> getTraitMsg(); //Phpstorm freaks out here
}
}
接口I{
函数foo();
}
性状T{
/**
*@返回字符串
*/
公共函数gettraitsg()
{
返回“我是一种特质”;
}
}
A级执行器I{
使用T;
函数foo(){}
}
C类实现I{
使用T;
函数foo(){}
}
B类{
/**
*@param I$input gettraitsg();//Phpstorm在这里异常
}
}
我的问题在评论中。如何指示
$input
参数实现I
并使用T
?AFAIK您不能以这种方式键入提示特征用法(@param
仅接受标量类型或类/接口+一些)
理想的解决方案是将gettraitsg()
声明放入I
接口中
如果不能做到这一点。。然后您可以指定此处只能传递A
或C
的实例(因为它们利用了该特性):
如果此类可能类的名称事先未知(例如,它是一个库代码,最终类可以是每个新项目中的任何内容,甚至可以随时添加到当前项目中)。。然后,我建议使用安全措施,无论如何,您都应该在此类代码中使用安全措施(通过方法\u exists()
):
为什么要使用安全防护?因为您可以传递另一个类K
的实例,该类实现I
,但不使用traitT
。在这种情况下,没有防护装置的代码将被破坏
只是想澄清一下:您可以使用
@param I | T$input
指定该方法期望实现I
或使用T
的实例。。但是它只适用于PhpStorm(不确定其他IDE)——AFAIK它不被实际的PHPDocumentor接受,并且似乎不适合PHPDoc。AFAIK您不能以这种方式键入提示特性用法(@param
只接受标量类型或类/接口+一些)
理想的解决方案是将gettraitsg()
声明放入I
接口中
如果不能做到这一点。。然后您可以指定此处只能传递A
或C
的实例(因为它们利用了该特性):
如果此类可能类的名称事先未知(例如,它是一个库代码,最终类可以是每个新项目中的任何内容,甚至可以随时添加到当前项目中)。。然后,我建议使用安全措施,无论如何,您都应该在此类代码中使用安全措施(通过方法\u exists()
):
为什么要使用安全防护?因为您可以传递另一个类K
的实例,该类实现I
,但不使用traitT
。在这种情况下,没有防护装置的代码将被破坏
只是想澄清一下:您可以使用
@param I | T$input
指定该方法期望实现I
或使用T
的实例。。但它只适用于PhpStorm(不确定其他IDE)--因为它不被实际的PHPDocumentor接受,并且似乎不适合PHPDoc。这有点老套,但您可以使用类使用它返回已使用特征的列表。并在PHPDoc中将T
作为@param类型添加到autocomplete中
class B {
/**
* @param I|T $input <===Is there anyway to specify that $input use T?
*/
public function doSomethingCool($input){ //An instance of "A" or "C"
$uses = class_uses(get_class($input));
if (!empty($uses['T'])) {
echo $input->getTraitMsg(); //Phpstorm freaks out here
}
}
}
B类{
/**
*@param I | T$input gettraitsg();//Phpstorm在这里疯狂了
}
}
}
这有点老套,但您可以使用class\u uses
它返回已使用特征的列表。并在PHPDoc中将T
作为@param类型添加到autocomplete中
class B {
/**
* @param I|T $input <===Is there anyway to specify that $input use T?
*/
public function doSomethingCool($input){ //An instance of "A" or "C"
$uses = class_uses(get_class($input));
if (!empty($uses['T'])) {
echo $input->getTraitMsg(); //Phpstorm freaks out here
}
}
}
B类{
/**
*@param I | T$input gettraitsg();//Phpstorm在这里疯狂了
}
}
}
“//Phpstorm在这里疯了”--不,不是。它只是试图向您发出代码不正确的信号
方法doSomethingCool()
的契约不要求$input
公开任何名为gettraitsg()
的方法。docblock说它应该实现接口I
,但docblock不是代码,它只帮助PhpStorm提供验证和建议
由于您没有键入提示参数$input
,因此代码:
$b = new B();
$b->doSomethingCool(1);
$b = new B();
$b->doSomethingCool(1);
有效,但当它尝试执行行$msg=$input->gettraitsg()时就会崩溃代码>
如果要在$input
上调用gettraitsg()
,必须:
- 声明
$input
的类型李>
- 确保声明的
$input
类型公开名为gettraitsg()
的方法
对于第一步,您现有的B类代码应为:
class B {
/**
* @param I $input
*/
public function doSomethingCool(I $input) {
$msg = $input -> getTraitMsg();
}
}
请在参数列表中的参数$input
前面注明类型I
完成下一步的最简单方法是将方法gettraitsg()
声明到接口I
:
interface I {
function foo();
function getTraitMsg();
}
现在,代码:
$b = new B();
$b->doSomethingCool(1);
$b = new B();
$b->doSomethingCool(1);
当异常到达行$b->doSomethingTool(1)时引发异常代码>(即在进入功能之前)。这是PHP告诉您该方法没有使用正确的参数调用的方式。无论是A
还是C
类型,都必须向其传递一个实现接口I
的对象。它可以是实现接口I的任何其他类型,没有人关心它是否使用trait T来实现它。“//Phpstorm在这里崩溃了”--不,它不是。它只是试图向您发出代码不正确的信号
方法doSomethingCool()
的契约不要求$input
公开任何名为gettraitsg()
的方法。docblock说的没错