My PHP code is structured to be something like follows (this structure is unchangeable):
class BaseFooClass {
}
class ChildFooClass1 extends BaseFooClass {
}
class ChildFooClass2 extends BaseFooClass {
}
//... (there are like a hundred child foo classes)
class BaseBarClass {
protected function getFooBase($input) : BaseFooClass
{
$class = "ChildFooClass" . $input;
return new $class();
}
}
class ChildBarClass1 extends BaseBarClass {
public function getFoo() : ChildFooClass1
{
return $this->getFooBase(1);
}
}
Now in the getFoo()
function in ChildBarClass1
, PhpStorm will give the warning "Return value is expected to be 'ChildFooClass1', 'BaseFooClass' returned " and it correctly does so.
However I want a clean code with no warning without changing this structure.
I tried the following by adding PHP doc:
public function getFoo() : ChildFooClass1
{
/** @var ChildFooClass1 $foo **/
$foo = $this->getFooBase(1);
return $foo;
}
However this time it gives a different warning "Unnecessary local variable" and ask me to inline it back.
Is there a good way to get rid of the warnings?
EDIT: the following is tried too but still the warning of "Return value is expected ..." is showing up.
/**
* @return ChildFooClass1
*/
public function getFoo() : ChildFooClass1
{
return $this->getFooBase(1);
}
CodePudding user response:
Given your code BaseBarClass::getFooBase()
returns a BaseFooClass
while ChildBarClass1::getFoo()
wants to return a ChildFooClass1
.
This violates php's Covariance/Contravariance rules, by which you can only return a more specifc type not a more general type, of which PhpStorm correctly warns you about.
So you could either adhere to this rule (good) and refactor your code or suppress the error (bad).
E.g.:
// corrected type:
class ChildBarClass1 extends BaseBarClass
{
public function getFoo(): BaseFooClass
{
return $this->getFooBase(1);
}
}
// error suppressed:
class ChildBarClass1 extends BaseBarClass
{
public function getFoo(): ChildFooClass1
{
/** @noinspection PhpIncompatibleReturnTypeInspection */
return $this->getFooBase(1);
}
}