问题描述
我想知道为什么PHP Trait(PHP 5.4)无法实现接口。
I'm wondering why PHP Trait (PHP 5.4) cannot implement interfaces.
从user1460043的回答更新=> ...不能要求使用的类它实现了一个特定的界面
我明白这很明显,因为人们可以认为如果 A类
正在使用 Trait T
,它实现接口I
,而不是 A类
应该直接实现接口我
(这不是真的,因为 A类
可以重命名trait方法)。
I understand that it could be obvious, because people could think that if a Class A
is using a Trait T
which is implementing an interface I
, than the Class A
should be implementing the interface I
undirectly (and this is not true because Class A
could rename trait methods).
在我的例子中,我的特性是从使用trait的类实现的接口调用方法。
In my case, my trait is calling methods from the interface that the class using the trait implements.
该特征实际上是该接口的某些方法的实现。
所以,我想在代码中设计每个想要使用我的特性的类都必须实现该接口。这将允许Trait使用接口定义的类方法,并确保它们存在于类中。
The trait is in fact an implementation of some methods of the interface.So, i want to "design" in the code that every class that want to use my trait have to implement the interface. That would allow the Trait to use class methods defined by the interface and be sure they are existing in the class.
推荐答案
真的简短版本更简单,因为你不能。这不是Traits的工作方式。
The really short version is simpler because you can't. That's not how Traits work.
当你在PHP中编写使用SomeTrait;
时,你(有效地)告诉编译器将Trait中的代码复制并粘贴到正在使用它的类中。
When you write use SomeTrait;
in PHP you are (effectively) telling the compiler to copy and paste the code from the Trait into the class where it's being used.
因为使用SomeTrait;
在类中,它不能将实现SomeInterface
添加到类中,因为它必须在类之外。
Because the use SomeTrait;
is inside the class, it can't add implements SomeInterface
to the class, because that has to be outside the class.
因为他们不能实例化。特征实际上只是一个(告诉编译器将特征代码复制并粘贴到此类中)而不是可以由代码引用的对象或类型。
Because they can't be instantiated. Traits are really just a language construct (telling the compiler to copy and paste the trait code into this class) as opposed to an object or type that can be referenced by your code.
可以使用抽象类强制执行使用
特征,然后从中扩展类。
That can be enforced using an abstract class to use
the trait and then extending classes from it.
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的类具有特定方法,我认为你可能正在使用特征,你应该首先使用抽象类。
However - if you do need to enforce that any class that uses a Trait has a particular method, I think you may be using traits where you should have been abstract classes in the first place.
或者说你的逻辑错误。您的目的是要求实现接口的类具有某些功能,而不是如果它们具有必须将其自身声明为实现接口的某些功能。
Or that you have your logic the wrong way round. You're meant to require classes that implement interfaces have certain functions, not that if they have certain functions that they must declare themselves as implementing an interface.
编辑
实际上,您可以在Traits中定义抽象函数以强制类实现该方法。例如
Actually you can define abstract functions inside Traits to force a class to implement the method. e.g.
trait LoggerTrait {
public function debug($message, array $context = array()) {
$this->log('debug', $message, $context);
}
abstract public function log($level, $message, array $context = array());
}
但是这仍然不允许你在特征中实现接口,并且仍然闻起来像一个糟糕的设计,因为界面比定义一个类需要履行的合同的特性要好得多。
However this still doesn't allow you to implement the interface in the trait, and still smells like a bad design, as interfaces are much better than traits at defining a contract that a class needs to fulfill.
这篇关于为什么PHP Trait无法实现接口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!