새로운 자기 대 새로운 정적


513

PHP 5.2에서 작동하도록 PHP 5.3 라이브러리를 변환하고 있습니다. 내 방식으로 서있는 가장 중요한 것은 같은 정적 바인딩을 사용 return new static($options);하는 return new self($options)것입니다. 이를 변환 하면 동일한 결과를 얻을 수 있습니까?

차이점은 무엇이며 new self그리고 new static?

답변:


890

같은 결과를 얻을 수 있습니까?

실제로는 아닙니다. 그래도 PHP 5.2의 해결 방법을 모르겠습니다.

차이점은 무엇이며 new self그리고 new static?

selfnew키워드가 실제로 작성된 것과 동일한 클래스를 나타냅니다 .

static, PHP 5.3의 늦은 정적 바인딩에서 계층 구조에서 메소드를 호출 한 클래스를 가리 킵니다.

다음 예제에서는에서 B두 메소드를 모두 상속합니다 A. self호출이 바인딩 A이 정의 있기 때문에 A반면, 첫 번째 방법의의 구현을 static호출 클래스에 바인드됩니다 (참조 get_called_class()).

class A {
    public static function get_self() {
        return new self();
    }

    public static function get_static() {
        return new static();
    }
}

class B extends A {}

echo get_class(B::get_self());  // A
echo get_class(B::get_static()); // B
echo get_class(A::get_self()); // A
echo get_class(A::get_static()); // A

맞는 말이다. 가장 좋은 방법은 클래스 이름을 늦은 정적 바인딩을 사용하는 함수에 전달한 다음 새로운 $ className ($ options)을 반환하는 것입니다.
Mike

12
클래스 이름을 "통과"할 필요는 없으며 항상 할 수 있습니다 get_called_class(). 이는 __CLASS__사실상와 동일 하지만 LSB와 호환됩니다.
shadowhand

7
<PHP5.3에 get_called_class가 없습니다. 따라서 PHP5.2에서 인스턴스화 된 객체의 클래스 이름을 얻으려면이 함수는 라이브러리를 PHP 5.3에서 PHP 5.2로 변환 할 때 도움이되지 않습니다.
txwikinger

2
self :: theFunction ()이라는 함수는 "물리적으로 속한 클래스의 컨텍스트에서 실행합니다"와 같이 작동합니다. static :: theFunction () 함수는 "실제 외부에서 호출 한 클래스의 컨텍스트에서 실행합니다"와 같이 작동합니다. (상속 시나리오 가정). 감사합니다
Shubhranshu

2
내 머리 속에는 직관적 인 것을 취하고 반대 방향으로 만듭니다. 이름을 기반으로 생각 self하고 스스로를 static반환하고 재정의 할 수없는 것을 반환 할 것입니다 ...하지만 lo는 반대입니다. PHP의 이름, 규칙 및 전체적인 스타일에 감명을받지 않습니다. -_-
ahnbizcad

23

이 코드의 메서드가 정적이 아닌 경우을 사용하여 5.2에서 해결 방법을 얻을 수 있습니다 get_class($this).

class A {
    public function create1() {
        $class = get_class($this);
        return new $class();
    }
    public function create2() {
        return new static();
    }
}

class B extends A {

}

$b = new B();
var_dump(get_class($b->create1()), get_class($b->create2()));

결과 :

string(1) "B"
string(1) "B"

17
메소드가 정적이 아닌 경우 늦은 정적 바인딩은 완전히 관련이 없습니다.
BoltClock

1
예를 들어, "복사"방법에서 객체를 사용할 수 clone있지만 속성을 다시 만들고 설정하기 만하면됩니다. $copy = new static(); $copy->set($this->get()); return $copy;
Marius Balčytis 1

9
@BoltClock 확실하지 않습니까? 서브 클래스의 인스턴스 메소드 내에서 재정의 된 정적 메소드를 호출하는 경우 해당 정적 메소드 의 기본 클래스 또는 서브 클래스 버전 사용 여부에 대한 선택 self::또는 static::영향을받습니다. 그러한 상황이 본질적으로 나쁜 습관을 나타내는 것이라고 생각할 어떤 이유가 없다면 (그리고 이것이 왜 그렇게 해야하는지 아무 이유도 보지 못합니다), 비 정적 방법과 그 사이의 선택 self::과 그 사이의 선택 static::정적 메소드. 나는 당신의 의견을 잘못 이해 했습니까, 아니면 우리가 단순히 틀린 것입니까?
Mark Amery

4
@ Mark Amery : 흠. 당신 말이 맞아요 문제의 인스턴스 메소드에서 정적 메소드가 호출되지 않는다고 가정했지만, 귀하의 예를 바탕으로, 이것이 매우 순진한 가정이 될 수 있음을 알 수 있습니다.
BoltClock


7

다른 사람의 답변 외에도 :

static ::은 런타임 정보를 사용하여 계산됩니다.

static::속성 값 때문에 클래스 속성에서 사용할 수 없습니다 .

컴파일 타임에 평가할 수 있어야하며 런타임 정보에 의존해서는 안됩니다.

class Foo {
    public $name = static::class;

}

$Foo = new Foo;
echo $Foo->name; // Fatal error

사용 self::

class Foo {
    public $name = self::class;

}
$Foo = new Foo;
echo $Foo->name; // Foo

내가 작성한 코드의 치명적 오류 주석은 오류가 발생한 위치를 나타내지 않으며, 주석에서 언급 된 @Grapestain으로 객체가 인스턴스화되기 전에 오류가 발생했습니다.


4
public $name = static::class;예제에서 제안한대로 오류는 7 행이 아닌 2 행에 발생합니다 . 오류 : "정적 :: 클래스를 컴파일 타임 클래스 이름 확인에 사용할 수 없습니다"는 문제가 $ name 필드에 액세스하려고하지 않고 PHP 클래스를 컴파일 할 때 훨씬 이전에 있음을 나타냅니다. 첫 번째 예에서는 7 행 (또는 6 행)에 도달하지 않습니다.
sbnc.eu

@Grapestain이 예제에서 작성한 의견은 최종 결과를 표시하고 오류가 실제로 발생한 위치를 나타내지 않았습니다. 어쨌든 지적 해 주셔서 감사합니다.
Rain

그렇습니다. 나는 비난을 의미하지 않았습니다. 그것이 다른 사람들을 도울 수 있기를 희망하면서 저를 먼저 혼란스럽게 한 것을 분명히했습니다. 어쨌든 유용한 예!
sbnc.eu
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.