Program Tip

PHP Trait이 인터페이스를 구현할 수없는 이유는 무엇입니까?

programtip 2020. 10. 12. 08:04
반응형

PHP Trait이 인터페이스를 구현할 수없는 이유는 무엇입니까?


PHP Trait (PHP 5.4)가 인터페이스를 구현할 수없는 이유가 궁금합니다.

user1460043의 답변에서 업데이트 => ... 특정 인터페이스를 구현하는 데 사용하는 클래스가 필요하지 않습니다.

나는 사람들이이 경우에 있다고 생각할 수 있기 때문에, 분명이 될 수 있음을 이해 Class A사용 Trait T를 구현하는이 interface I(가)보다, Class A이행되어야한다 interface Iundirectly을 (이 사실 때문에없는 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이 인터페이스에 의해 정의 된 클래스 메서드를 사용하고 클래스에 존재하는지 확인할 수 있습니다.

이것은 매우 합리적으로 들리며 귀하의 디자인에 문제가 있다고 말하지 않습니다. 이 아이디어를 염두에두고 특성이 제안되었습니다. 여기에서 두 번째 요점을 참조하십시오.

  • 트레이 트는 동작을 구현하는 일련의 메서드를 제공 합니다.
  • 트레이 트 에는 제공된 동작에 대한 매개 변수 역할을하는 메소드 세트가 필요 합니다.
  • [...]

Schärli et al, Traits : Composable Units of Behaviour, ECOOP'2003, LNCS 2743, pp. 248–274, Springer Verlag, 2003, 페이지 2

따라서 특성 이 "구현"하는 것이 아니라 인터페이스 필요하도록 하는 것이 더 적절할 수 있습니다.

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();
        }
    }
}

So the trait isn't completely dependent on the interface, but a proposal to implement one of its functions, since when using the trait the class will demand the implementation of the abstract methods.

Final design

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.
    }
}

Please excuse my English

참고URL : https://stackoverflow.com/questions/14665978/why-php-trait-cant-implement-interfaces

반응형