특성은 유전되지 않습니다

4681 단어 webdevtutorialphp
나는 최근에 Jess Archer 의 이 트윗을 보았습니다. 언뜻 보기에는 이해가 되지 않을 수 있는 Trait 행동을 보여주었습니다. 왜 이런 일이 발생하는지 설명하는 것이 재미있을 것이라고 생각했습니다.









제스 아처


@jessarchercodes






이 동작은 저를 놀라게 했습니다!(또한 "활성화"라고 말하는 것을 좋아합니다)


오전 00:53 - 2021년 8월 24일








Enableable라고 말하면서 멋지고 모두. TimeCircuits::$enabled 변수가 false 특성에서 명확하게 업데이트되었을 때 여전히 Enableable 일 수 있는 방법은 무엇입니까? 정답은 특성은 유전되지 않는다는 것입니다.

단일 상속 대 구성



PHP는 소위 Single Inheritance language으로, 모든 class은 하나의 부모로부터만 컨텍스트를 상속할 수 있음을 의미합니다. 대부분의 경우 이것은 잘 작동하지만 때로는 재사용하려는 클래스에 코드가 있습니다. 이것을 사용하려는 클래스가 이미 extends 다른 클래스인 경우 불가능합니다. 이것이 PHP가 특성을 도입한 이유입니다.

특성은 여러 클래스 내에서 사용할 수 있는 일종의 미니 클래스입니다. 클래스와 마찬가지로 메서드, 매개 변수, 정적 메서드 및 정적 변수를 가질 수 있습니다. private , protectedpublic 과 같은 가시성도 동일하게 작동합니다. 그러나 extends 을 사용하여 이러한 특성에서 상속하는 대신 클래스 내부의 특성을 use 해야 합니다. 자체적으로는 특성을 인스턴스화할 수 없기 때문에 실제로 클래스 내부의 특성을 use 해야 합니다. 클래스는 또한 여러 특성을 가질 수 있습니다. 이렇게 하면 재사용 가능한 작은 코드 조각으로 구성된 새 클래스를 구성할 수 있습니다.

특성을 복사하여 붙여넣습니다.



트레이트가 다른 클래스처럼 보이지만 확장하는 대신 이 use -ing은 큰 차이를 만듭니다. 특성을 use하면 특성의 현재 상태가 클래스에 복사됩니다. 그리고 이 복사는 useTimeCircuits 특성의 변경에 영향을 받지 않는 이유입니다. 이 변수를 상속하지 않습니다. 자체 사본이 있습니다. 그리고 Enableable 클래스가 생성되기 전에 매개변수가 true으로 설정되었기 때문에 이 클래스에는 해당 상태의 복사본이 있습니다. 따라서 마지막에 FluxCapacitorEnableable::$enabled 으로 재설정해도 false 또는 TimeCircuits 에는 영향을 미치지 않습니다. 완전히 별개의 매개변수입니다.

클래스 상속



클래스가 유사한 상황에 어떻게 반응하는지 봅시다. FluxCapacitor 매개변수가 있는 Base 클래스와 static $enabled (따라서 Extended 에서 상속받는) extends 클래스를 만듭니다. 그런 다음 이 변수의 값을 변경할 때 어떤 일이 발생하는지 확인하십시오.

class Base {
    public static $enabled = false;
}

class Extended extends Base {
}

Base::$enabled = true;

var_dump(Base::$enabled, Extended::$enabled); // (bool) true, (bool) true


여기에서 상속이 작동하는 것을 볼 수 있습니다. Base 클래스의 매개변수를 업데이트할 때 확장 클래스는 실제로 사본이 아니라 동일한 매개변수를 참조하기 때문에 이 업데이트의 영향을 받습니다. 그리고 동일한 매개변수를 참조하고 있음을 증명하기 위해 Base 대신 Extended::$enabledtrue으로 변경할 수 있으며 결과는 여전히 동일합니다.

최종 노트



Jess가 이 특성을 동시에 사용하는 모든 클래스를 활성화하는 방법을 원했는지는 확실하지 않습니다. 그렇다면 두 가지 대안이 있습니다.
  • 해당 클래스가 이 매개변수가 있는 중간 클래스에서 확장되도록 합니다. 예를 들어 Base::$enabled은 이 매개변수가 있는 Model을 확장할 수 있습니다. 이 경우 EnableableModel 을 업데이트할 수 있습니다.
  • 이 특성을 사용하는 모든 클래스에 인터페이스를 등록하고 컨테이너에 넣습니다. 그런 다음 이 인터페이스가 있는 컨테이너에서 모든 클래스를 검색하고 모든 클래스를 개별적으로 업데이트합니다.

  • You might also be interested in my blog post on Testing Traits in PHPUnit. In this post I'll show you some handy tips and tricks for testing traits.

    좋은 웹페이지 즐겨찾기