PHP Trait (PHP 5.4)가 인터페이스를 구현할 수없는 이유가 궁금합니다.
user1460043의 답변에서 업데이트 => … 특정 인터페이스를 구현하는 데 사용하는 클래스가 필요하지 않습니다.
나는 사람들이이 경우에 있다고 생각할 수 있기 때문에, 분명이 될 수 있음을 이해 Class A
사용 Trait T
를 구현하는이 interface I
(가)보다, Class A
이행되어야한다 interface I
undirectly을 (이 사실 때문에없는 Class A
특성 방법의 이름을 바꿀 수있다).
제 경우에는 특성을 사용하는 클래스가 구현하는 인터페이스에서 메서드를 호출하는 특성이 있습니다.
특성은 사실 인터페이스의 일부 메소드의 구현입니다. 그래서 저는 제 특성을 사용하려는 모든 클래스가 인터페이스를 구현해야하는 코드를 “디자인”하고 싶습니다. 그러면 Trait이 인터페이스에 의해 정의 된 클래스 메서드를 사용하고 클래스에 존재하는지 확인할 수 있습니다.
답변
정말 짧은 버전은 할 수 없기 때문에 더 간단합니다. 그것은 특성이 작동하는 방식이 아닙니다.
use SomeTrait;
PHP로 작성할 때 (효과적으로) 컴파일러에게 Trait의 코드를 복사하여 사용중인 클래스에 붙여 넣도록 지시합니다.
use SomeTrait;
는 클래스 내부에 있기 때문에 implements SomeInterface
클래스 외부에 있어야하므로 클래스에 추가 할 수 없습니다 .
“PHP에 특성 유형이없는 이유는 무엇입니까?”
인스턴스화 할 수 없기 때문입니다. 트레이 트는 코드에서 참조 할 수있는 객체 나 유형 이 아니라 실제로 언어 구조 (컴파일러에게 트레이 트 코드를이 클래스에 복사하여 붙여 넣도록 지시)에 불과합니다 .
그래서 저는 제 특성을 사용하려는 모든 클래스가 인터페이스를 구현해야하는 코드를 “디자인”하고 싶습니다.
추상 클래스를 사용 use
하여 특성에 적용한 다음 클래스를 확장 할 수 있습니다.
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을 사용하는 모든 클래스가 특정 메서드를 갖도록 강요해야하는 경우, 처음에 추상 클래스 여야했던 트레이 트를 사용하고있을 수 있습니다.
또는 논리가 잘못되었다는 것입니다. 인터페이스를 구현하는 클래스에는 특정 기능이 있어야하며, 특정 기능이있는 경우 인터페이스를 구현하는 것으로 선언해야하는 것이 아닙니다.
편집하다
실제로 Traits 내부에 추상 함수를 정의하여 클래스가 메서드를 구현하도록 할 수 있습니다. 예 :
trait LoggerTrait {
public function debug($message, array $context = array()) {
$this->log('debug', $message, $context);
}
abstract public function log($level, $message, array $context = array());
}
그러나 이것은 여전히 특성에서 인터페이스를 구현하는 것을 허용하지 않으며, 클래스가 이행해야하는 계약을 정의 할 때 특성보다 인터페이스가 훨씬 낫기 때문에 여전히 나쁜 디자인처럼 냄새가납니다.
답변
있다 RFC는 : 인터페이스 특색가 언어에 추가 할 다음과 같은 제안 :
trait SearchItem implements SearchItemInterface
{
...
}
인터페이스에 필요한 메서드는 트레이 트에 의해 구현되거나 추상으로 선언 될 수 있으며,이 경우 트레이 트를 사용하는 클래스가이를 구현할 것으로 예상됩니다.
이 기능은 현재 해당 언어에서 지원되지 않지만 검토 중입니다 (RFC의 현재 상태 : 논의 중 ).
답변
[…] 내 특성을 사용하려는 모든 클래스가 인터페이스를 구현해야하는 코드에서 “디자인”합니다. 그러면 Trait이 인터페이스에 의해 정의 된 클래스 메서드를 사용하고 클래스에 존재하는지 확인할 수 있습니다.
이것은 매우 합리적으로 들리며 귀하의 디자인에 문제가 있다고 말하지 않습니다. 이 아이디어를 염두에두고 특성이 제안되었습니다. 여기에서 두 번째 요점을 참조하십시오.
- 트레이 트는 동작을 구현하는 일련의 메서드를 제공 합니다.
- 트레이 트 에는 제공된 동작에 대한 매개 변수 역할을하는 메소드 세트가 필요 합니다.
- […]
따라서 특성이 인터페이스를 “구현”하는 것이 아니라 필요 로한다고 말하는 것이 더 적절할 것입니다.
PHP에서이 “특성 (소비자 클래스가 인터페이스를 구현해야 함)을 필요로한다”는 것이 불가능한 이유는 모르겠지만 현재는 누락 된 것 같습니다.
@Danack이 그의 답변 에서 언급했듯이, 트레이 트에서 추상 함수를 사용 하여 트레이 트 를 사용하는 클래스에서 “요구”할 수 있습니다. 불행히도 개인 기능으로 는 이것을 할 수 없습니다 .
답변
@Danack의 응답에 동의하지만 조금 보완하겠습니다.
정말 짧은 버전은 할 수 없기 때문에 더 간단합니다. 그것은 특성이 작동하는 방식이 아닙니다.
나는 당신이 요청한 것이 필요하고 언어 실패보다 디자인 문제로 더 명백한 경우를 거의 생각할 수 없습니다. 다음과 같은 인터페이스가 있다고 상상해보십시오.
interface Weaponize
{
public function hasAmmunition();
public function pullTrigger();
public function fire();
public function recharge();
}
인터페이스에 정의 된 함수 중 하나를 구현 하는 특성 이 생성 되었지만 프로세스에서 인터페이스에 의해 정의 된 다른 함수도 사용 하는 특성 이 생성되었습니다. 해당 기능 을 사용하는 클래스가 인터페이스를 구현하지 않으면 모든 기능이 방아쇠
trait Triggerable
{
public function pullTrigger()
{
if ($this->hasAmmunition()) {
$this->fire();
}
}
}
class Warrior
{
use Triggerable;
}
쉬운 해결책은 단순히 특성 을 사용하는 클래스가 이러한 기능을 구현하도록하는 것입니다.
trait Triggerable
{
public abstract function hasAmmunition();
public abstract function fire();
public function pullTrigger()
{
if ($this->hasAmmunition()) {
$this->fire();
}
}
}
따라서 특성 은 인터페이스 에 완전히 의존하는 것이 아니라 해당 기능 중 하나를 구현하기위한 제안입니다. 특성을 사용할 때 클래스는 추상 메서드의 구현을 요구하기 때문입니다.
최종 디자인
interface Weaponize
{
public function hasAmmunition();
public function pullTrigger();
public function fire();
public function recharge();
}
trait Triggerable
{
public abstract function hasAmmunition();
public abstract function fire();
public function pullTrigger()
{
if ($this->hasAmmunition()) {
$this->fire();
}
}
}
class Warrior implements Weaponize
{
use Triggerable;
public function hasAmmunition()
{
// TODO: Implement hasAmmunition() method.
}
public function fire()
{
// TODO: Implement fire() method.
}
public function recharge()
{
// TODO: Implement recharge() method.
}
}
제 영어 실례합니다