문제

PHP는 버전 5.3부터 시작하여 지원합니다 늦은 바인딩 정적 방법의 경우. 의심 할 여지없이 유용한 기능이지만 실제로 사용이 필요한 경우가 있습니다 (예 : 활성 레코드 패턴).

다음과 같은 예를 고려하십시오.

1. 편의 생성자 (::create())

class SimpleObject
{
    public function __construct() { /* ... */ }

    public static function create()
    {
        return new static; // or: return new self;
    }
}

이 클래스가 확장 될 수있는 경우 (그러나 동일한 패키지의 클래스에 의해 확장되지 않음), 늦게 정적 바인딩을 사용하여 확장하기 위해 ( ::create() 방법, 그리고 더 중요한 것은 그것을 기억하지 않고)?

참고 :이 관용구는 단지 구성된 개체에서 방법을 호출하는 데 불가능한 작업을 수행하는 데 사용됩니다. new SimpleObject()->doStuff() PHP에서 유효하지 않습니다.


2. 클래스 상수

class TagMatcher
{
    const TAG_PATTERN = '/\<([a-z\-]+?)\>/i';

    private $subject;

    public function construct($subject) { $this->subject = $subject; }

    public function getAllTags()
    {
        $pattern = static::TAG_PATTERN;
        preg_match_all($pattern, $this->subject);
        return $pattern[1];
    }
}

사용 이유 static:: 이 예에서는 이전 예와 유사합니다. 이 클래스는 확장하고 상수를 재정의하여 다르게 형성된 태그와 일치하도록 만들 수 있기 때문에 사용됩니다.


그래서, 그것을 모두 마무리하기 위해, 이러한 용도 (및 유사한 사용)는 늦은 정적 바인딩의 용도입니까? 눈에 띄는 성능이 있습니까? 또한 늦은 바인딩을 자주 사용하면 Opcode 캐시가 제공하는 전체 성능 향상이 줄어 듭니까?

도움이 되었습니까?

해결책

그래서, 그것을 모두 마무리하기 위해, 이러한 용도 (및 유사한 사용)는 늦은 정적 바인딩의 용도입니까? 눈에 띄는 성능이 있습니까? 또한 늦은 바인딩을 자주 사용하면 Opcode 캐시가 제공하는 전체 성능 향상이 줄어 듭니까?

늦은 정적 바인딩의 도입은 PHP의 객체 모델에서 결함을 해결합니다. 그것은 성능에 관한 것이 아니라 의미론에 관한 것입니다.

예를 들어, 메소드 구현이 사용되지 않을 때마다 정적 메소드를 사용하는 것을 좋아합니다. $this. 메소드가 정적이기 때문에 때때로 그것을 무시하고 싶지 않다고 말하는 것은 아닙니다. PHP 5.3 이전에는 정적 메소드를 무시하면 오류가 표시되지 않았지만 PHP는 계속해서 부모의 버전을 조용히 사용합니다. 예를 들어, 아래 코드는 PHP 5.3 전에 'A'를 인쇄합니다. 그것은 예상치 못한 행동입니다.

늦은 정적 바인딩은이를 수정하고 이제 동일한 코드가 'B'를 인쇄합니다.

<?php
class A {
  public static function who() {
    echo __CLASS__;
  }
  public static function test() {
    static::who();
  }
}

class B extends A {
  public static function who() {
    echo __CLASS__;
  }
}

B::test();
?>

다른 팁

정적 방법 (초기 또는 후반)은 단단한 커플 링을 생성하고 (따라서) 테스트 가능성을 줄입니다. 정적 통화 이상을 사용하지 않고도 PHP에서 큰 프로그램을 만들 수 있습니다. 저에게는 늦은 정적 방법은 비 기능입니다.

편집하다 Marco Demaio의 질문에 답하기 위해 정적 방법은 테스트 성을 어떻게 줄입니까?

이것이 당신에게 분명하다면 죄송합니다, 정적 멤버 (데이터 및 방법 모두) ~이다 책임감있게 사용되면 유용하고 해를 입지 않아도, 나는 그들의 일반적인 오용을 암시하고있었습니다.

SQL 데이터베이스를 사용하는 웹 응용 프로그램이 있다고 가정 해 봅시다. 비즈니스 객체는 정적 인터페이스 또는 다형성을 통해 데이터를 검색 할 수 있습니다. 어느 하나

class MyBusinessObject
extends...
{
  public function doThisOrThat(...)
  {
    $results = db::query('sql string...');
    ...
  }
}

또는

class MyBusinessObject
extends...
{
  public function __construct(dbconn $db)
  {
    $this->db = $db;
  }
  private $db;
  public function doThisOrThat(...)
  {
    $results = $this->db->query('sql string...');
    ...
  }
}

후자는 테스트하기가 더 쉽습니다 (다음과 같이 : 그러한 입력으로 구성된 SQL 문자열이 그와 같은 사람임을 테스트하고 싶습니다). dbconn 의미를 변경하는 것보다 인터페이스 db::. 왜 당신도 원하는지? SQL 작용 동작을 테스트하기 위해 실제 데이터베이스가 필요하지 않기 때문에 실제로 테스트하기가 더 쉽습니다. 없이 실제 데이터베이스. 또한 테스트가 컷의 다른 측면 (테스트중인 코드)과 관련이있는 경우 SQL 소비자를 스텁하는 것이 더 쉽습니다.

테스트는 항상 공동 작업자에 대한 테스트 된 코드에 누워 있고 정적 인터페이스 ( "Doublecolon"또는 "Quadridot")에서 기권하는 것을 의미합니다. 거짓말은 대규모 수술 일 필요가 없음을 의미합니다. 생산 코드는 테스트 결과가 덜 의미가 있습니다.

늦은 정적 바인딩을 사용해야 할 필요가있는 경우 PHPUnit으로 단위 테스트를위한 정적 방법을 조롱하는 것입니다. 내가 가진 문제는 조롱을 허용하기 위해 코드를 엄격히 바꾸는 것을 좋아하지 않지만 그것을 극복 할 수 있다는 것입니다.

그러나 귀하의 질문에 답하기 위해, 나는 이것이 어떤 성능 비용이 들지 않든 대부분의 프로그램 런타임과 비교할 때 창백해질 것입니다. 다시 말해, 그것은 눈에 띄는 차이를 만들지 않을 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top