Php 如果适配器类需要类型提示怎么办?(菲律宾)

Php 如果适配器类需要类型提示怎么办?(菲律宾),php,adapter,Php,Adapter,这是一个基本的、有效的例子: class Test { public function test() { return 'a'; } } /** * @mixin Adapter */ class TestAdapter { /** * @var Test */ private $test; public function __construct(Test $test) { $th

这是一个基本的、有效的例子:

class Test
{
    public function test()
    {
        return 'a';
    }
}

/**
 * @mixin Adapter
 */
class TestAdapter
{
    /**
     * @var Test
     */
    private $test;

    public function __construct(Test $test)
    {
        $this->test = $test;
    }

    public function __call($method, $args)
    {
        switch($method)
        {
            case 'test' :
                return 'decorated: '.$this->test();
            default :
                throw new \Exception('Unhandled method call: '.$method);
        }
    }
}

$test = new Test();
$testAdapter = new TestAdapter($test);
$testAdapter->test();
到目前为止还不错。但是如果某人需要这个
测试怎么办?如果抽象出现了呢

abstract class TestAbstract
{
    public abstract function t();
}

class Test extends TestAbstract
{
    public function t()
    {
        return 't';
    }

    public function test()
    {
        return 'test';
    }
}

class WannaTest
{
    public function __construct(Test $test)
    {
    }
}
这样:

$test = new Test();
$testAdapter = new TestAdapter($test);
$wannaTest = new WannaTest($testAdapter); // would throw fatal!
这不起作用,因为
WannaTest
需要
Test
。 当然,我可以扩展
TestAdapter

class TestAdapter extends Test
{
    public function t()
    {
        // now I cant mock it!
    }
}

但在这种情况下,如果我有10个抽象方法,我就必须实现它们,即使其中一个只被使用。这样我就不能用
\u call
作为代理。所以有点臭。如何解决这个问题?删除typehint不是一个选项…

您可以创建一个内联类,该类扩展
Test
,并根据需要装饰该方法。这里有一个例子

class TestDecorator //decorator sounds more appropriate
{

    public static function decorate(Test $test) {
       return new class($test) extends Test {
            private $test;
            public function __construct(Test $test) {
                 $this->test = $test;
            }
            public function test() { 
                return 'decorated: '.$this->test->test();
            }
        };

    }
}
$test = new Test(); 
$decorated = TestDecorator::decorate($test);
echo $decorated->test();

类型提示
Test
现在应该可以工作了,因为修饰类实际上扩展了
Test

这基本上是我的第二个建议,作为匿名类:)