为什么PHP Trait不能实现接口?
我想知道为什么PHP Trait(PHP 5.4)不能实现接口。
从user1460043的答案更新=> …不能要求类使用它来实现一个特定的接口
我明白,这可能是显而易见的,因为人们可能会认为,如果一个Class A
正在使用一个实现interface I
的Trait T
,那么Class A
应该是非直接实现interface I
(这是不正确的,因为Class A
可以重命名特征方法)。
就我而言,我的特质是从接口中调用使用特征的类实现的方法。
这个特性实际上是一些接口方法的实现。 所以,我想在代码中“devise”每一个想要使用我的特质的类都必须实现这个接口。 这将允许Trait使用接口定义的类方法,并确保它们存在于类中。
真的很短的版本更简单,因为你不能。 这不是特质的工作方式。
当你写use SomeTrait;
在PHP中,您(有效地)告诉编译器将Trait中的代码复制并粘贴到正在使用的类中。
因为use SomeTrait;
是在类的内部,它不能添加implements SomeInterface
的类,因为那必须在类之外。
“为什么不是PHP中的Traitstypes?”
因为它们不能被实例化。 特征实际上只是一种语言结构 (告诉编译器将特征代码复制并粘贴到这个类中),而不是可以被代码引用的对象或types。
所以,我想在代码中“devise”每一个想要使用我的特质的类都必须实现这个接口。
可以使用抽象类来强制使用特征,然后从中扩展类。
interface SomeInterface{ public function someInterfaceFunction(); } trait SomeTrait { function sayHello(){ echo "Hello my secret is ".static::$secret; } } abstract class AbstractClass implements SomeInterface{ use SomeTrait; } class TestClass extends AbstractClass { static public $secret = 12345; //function someInterfaceFunction(){ //Trying to instantiate this class without this function uncommented will throw an error //Fatal error: Class TestClass contains 1 abstract method and must therefore be //declared abstract or implement the remaining methods (SomeInterface::doSomething) //} } $test = new TestClass(); $test->sayHello();
但是,如果你确实需要强制任何使用Trait的类都有一个特定的方法,那么我认为你可能使用的是首先应该是抽象类的特性。
或者你有你的逻辑错误的方式。 你的意思是要求实现接口的类具有某些function,而不是如果它们具有某些必须声明为实现接口的function。
编辑
实际上你可以在Traits中定义抽象函数来强制类实现这个方法。 例如
trait LoggerTrait { public function debug($message, array $context = array()) { $this->log('debug', $message, $context); } abstract public function log($level, $message, array $context = array()); }
然而,这仍然不允许你在特性中实现接口,而且仍然闻起来像一个糟糕的devise,因为接口在定义一个类需要履行的合同方面要比特性好得多。
有一个RFC:接口的特征build议以下将添加到该语言:
trait SearchItem implements SearchItemInterface { ... }
接口所要求的方法既可以通过特征来实现,也可以被声明为抽象的,在这种情况下,期望使用特征的类实现它。
此function目前不受该语言支持,但正在考虑中(RFC的当前状态为“ 正在讨论中” )。
在代码中“devise”每一个想要使用我的特质的类都必须实现这个接口。 这将允许Trait使用接口定义的类方法,并确保它们存在于类中。
这听起来很合理,我不会说你的devise有什么问题。 记住了这个想法的特点,请看这里的第二点:
- 特质提供了一套实现行为的方法。
- 特质需要一组方法作为所提供行为的参数。
- […]
Schärli等,Traits:Composable Units of Behavior,ECOOP'2003,LNCS 2743,pp.248-274,Springer Verlag,2003,第2页
所以,说你想要一个特质需要一个接口,而不是“实现”它可能会更合适。
我没有看到为什么在PHP中有这样的“特性要求(它的消费者类实现)接口”function是不可能的,但是现在看来似乎已经不存在了。
正如@Danack在他的回答中指出的那样,你可以在特质中使用抽象函数来从使用特质的类中“要求”它们。 不幸的是,你不能用私人function来做到这一点。