如果需要提示输入适配器类怎么办? (php)

时间:2019-01-30 21:12:15

标签: php adapter

一个基本的可行示例:

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();
到目前为止,一切都很好。但是,如果某人需要此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个抽象方法,即使只使用其中一个,我也必须实现它们。这样,我既不能使用__call作为代理。所以有点臭。如何解决?不能删除typehint ...

1 个答案:

答案 0 :(得分:1)

您可以创建扩展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