문제

PHP 5에서 사용의 차이점은 무엇입니까? self 그리고 $this?

각각은 언제 적절합니까?

도움이 되었습니까?

해결책

짧은 대답

사용 $this 현재 객체를 참조합니다. 사용 self 현재 클래스를 참조합니다. 다시 말해, 사용하십시오 $this->member 비 정적 구성원의 경우 사용하십시오 self::$member 정적 멤버를 위해.

전체 답변

다음은 다음과 같습니다 옳은 사용 $this 그리고 self 비 정적 및 정적 멤버 변수의 경우 :

<?php
class X {
    private $non_static_member = 1;
    private static $static_member = 2;

    function __construct() {
        echo $this->non_static_member . ' '
           . self::$static_member;
    }
}

new X();
?>

다음은 다음과 같습니다 잘못된 사용 $this 그리고 self 비 정적 및 정적 멤버 변수의 경우 :

<?php
class X {
    private $non_static_member = 1;
    private static $static_member = 2;

    function __construct() {
        echo self::$non_static_member . ' '
           . $this->static_member;
    }
}

new X();
?>

다음은 다음과 같습니다 다형성 ~와 함께 $this 멤버 기능 :

<?php
class X {
    function foo() {
        echo 'X::foo()';
    }

    function bar() {
        $this->foo();
    }
}

class Y extends X {
    function foo() {
        echo 'Y::foo()';
    }
}

$x = new Y();
$x->bar();
?>

다음은 다음과 같습니다 다형성 행동 억제 사용하여 self 멤버 기능 :

<?php
class X {
    function foo() {
        echo 'X::foo()';
    }

    function bar() {
        self::foo();
    }
}

class Y extends X {
    function foo() {
        echo 'Y::foo()';
    }
}

$x = new Y();
$x->bar();
?>

아이디어는 그 것입니다 $this->foo() 전화 foo() 현재 객체의 정확한 유형이든 멤버 기능. 대상이 있다면 type X, 따라서, 그것은 전화합니다 X::foo(). 대상이 있다면 type Y, 그것은 전화합니다 Y::foo(). 그러나 자기 :: foo (), X::foo() 항상 호출됩니다.

에서 http://www.phpbuilder.com/board/showthread.php?t=10354489:

에 의해 http://board.phpbuilder.com/member.php?145249-laserlight

다른 팁

키워드 자체가합니다 아니다 적어도 정적 멤버로 당신을 제한하는 방식이 아닌 '현재 클래스'를 참조하십시오. 비 정적 구성원의 맥락에서 self 또한 vtable을 우회하는 방법을 제공합니다 (Vtable의 Wiki를 참조하십시오) 현재 객체의 경우. 당신이 사용할 수있는 것처럼 parent::methodName() 부모 버전의 함수를 호출하려면 self::methodName() 방법의 현재 클래스 구현을 호출합니다.

class Person {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }

    public function getTitle() {
        return $this->getName()." the person";
    }

    public function sayHello() {
        echo "Hello, I'm ".$this->getTitle()."<br/>";
    }

    public function sayGoodbye() {
        echo "Goodbye from ".self::getTitle()."<br/>";
    }
}

class Geek extends Person {
    public function __construct($name) {
        parent::__construct($name);
    }

    public function getTitle() {
        return $this->getName()." the geek";
    }
}

$geekObj = new Geek("Ludwig");
$geekObj->sayHello();
$geekObj->sayGoodbye();

이것은 출력됩니다 :

안녕하세요, 저는 Ludwig the Geek입니다
Ludwig에서 작별 인사

sayHello() 사용 $this 포인터, 따라서 vtable이 호출되도록 호출됩니다 Geek::getTitle(). sayGoodbye() 용도 self::getTitle(), 따라서 vtable은 사용되지 않습니다 Person::getTitle() 호출됩니다. 두 경우 모두, 우리는 인스턴스화 된 객체의 방법을 다루고 있으며 $this 호출 된 함수 내의 포인터.

사용하지 마세요 self::, 사용 static::

자아의 또 다른 측면이 있습니다 :: 언급 할 가치가 있습니다. 짜증나게 self:: 실행 지점이 아닌 정의 지점의 범위를 나타냅니다.. 두 가지 방법 으로이 간단한 클래스를 고려하십시오.

class Person
{

    public static function status()
    {
        self::getStatus();
    }

    protected static function getStatus()
    {
        echo "Person is alive";
    }

}

우리가 전화하면 Person::status() 우리는 "사람이 살아있다"는 것을 볼 것입니다. 이제 우리가 이것으로부터 상속되는 수업을 만들 때 어떤 일이 일어나는지 고려하십시오.

class Deceased extends Person
{

    protected static function getStatus()
    {
        echo "Person is deceased";
    }

}

부름 Deceased::status() 우리는 "사람이 사망 한 사람"을 볼 것으로 예상하지만, 우리가 보는 것은 "사람이 살아있다"는 범위에 전화시 원래의 메소드 정의가 포함되어 있기 때문입니다. self::getStatus() 정의되었습니다.

PHP 5.3에는 솔루션이 있습니다. 그만큼 static:: 해상도 연산자는 "늦은 정적 바인딩"을 구현하는데, 이는 그것이 호출 된 클래스의 범위에 묶여 있다고 말하는 멋진 방법입니다. 선을 변경하십시오 status() 에게 static::getStatus() 그리고 결과는 당신이 기대할 것입니다. 이전 버전의 PHP에서는이 작업을 수행하려면 Kludge를 찾아야합니다.

보다 PHP 문서

질문에 대답하기 위해 묻지 않은 질문에 대답하기 위해 ...

$this-> 현재 객체 (클래스 인스턴스)를 말하면 static:: 수업을 말합니다

우리가 이야기 할 때 우리가 말하는 것을 정말로 이해하려면 self ~ 대 $this, 우리는 실제로 개념적이고 실용적인 수준에서 무슨 일이 일어나고 있는지 파헤쳐 야합니다. 나는 답이 이것을 적절하게 수행한다고 생각하지 않으므로 여기에 내 시도가 있습니다.

무엇에 대해 이야기함으로써 시작합시다 수업 그리고 물체 이다.

개념적으로 수업과 사물

그래서, 무엇을 ~이다수업? 많은 사람들이 그것을 a로 정의합니다 청사진 또는 a 주형 물체를 위해. 사실, 당신은 더 많은 것을 읽을 수 있습니다 PHP의 수업에 대해 여기. 그리고 어느 정도는 그것이 실제로 바로 그 것입니다. 수업을 보자 :

class Person {
    public $name = 'my name';
    public function sayHello() {
        echo "Hello";
    }
}

알 수 있듯이 해당 클래스에 부르는 속성이 있습니다. $name 및 메소드 (함수)가 호출됩니다 sayHello().

이것의 매우 주목하는 것이 중요합니다 수업 정적 구조입니다. 이는 수업을 의미합니다 Person, 한 번 정의되면, 당신이 보는 곳마다 항상 동일합니다.

반면에 물체는 사례 수업의. 그 의미는 우리가 클래스의 "청사진"을 가져 와서 동적 사본을 만드는 데 사용한다는 것입니다. 이 사본은 이제 구체적으로 저장된 변수와 관련이 있습니다. 따라서 사례 해당 인스턴스의 로컬입니다.

$bob = new Person;
$adam = new Person;
$bob->name = 'Bob';
echo $adam->name; // "my name"

우리는 새로운 것을 창조합니다 인스턴스 The를 사용하는 클래스의 new 운영자.

따라서 우리는 클래스가 글로벌 구조이며 물체는 로컬 구조라고 말합니다. 그 재미에 대해 걱정하지 마십시오 -> 구문, 우리는 조금씩 들어갈 것입니다.

우리가 말해야 할 또 다른 것은 우리가 할 수 있다는 것입니다. 확인하다 인스턴스가 instanceof 특정 수업 : $bob instanceof Person 그것은 부울을 반환합니다 $bob 인스턴스를 사용하여 만들어졌습니다 Person 수업, 또는 아이의 아이 Person.

상태 정의

그래서 수업에 실제로 포함 된 내용을 조금 파헤쳐 봅시다. 수업에는 다음과 같은 5 가지 유형의 "사물"이 있습니다.

  1. 속성 -이를 각 인스턴스에 포함 할 변수로 생각하십시오.

    class Foo {
        public $bar = 1;
    }
    
  2. 정적 특성 -이를 클래스 수준에서 공유하는 변수로 생각하십시오. 각 인스턴스에 의해 복사되지 않음을 의미합니다.

    class Foo {
        public static $bar = 1;
    }
    
  3. 행동 양식 - 각 인스턴스에 포함 할 함수 (및 인스턴스에서 작동).

    class Foo {
        public function bar() {}
    }
    
  4. 정적 방법 -이 기능은 전체 클래스에서 공유되는 기능입니다. 그들이하다 ~ 아니다 인스턴스에서만 작동하지만 대신 정적 특성에서만 작동합니다.

    class Foo {
        public static function bar() {}
    }
    
  5. 상수 - 클래스 해결 상수. 여기에 더 깊이 가지 않고 완전성을 추가합니다.

    class Foo {
        const BAR = 1;
    }
    

기본적으로 우리는 "힌트"를 사용하여 클래스 및 객체 컨테이너에 대한 정보를 저장하고 있습니다. 공전 정보가 공유되는지 (따라서 정적)인지 아닌지 (따라서 역동적)를 식별합니다.

상태 및 방법

메소드 내부에서 객체의 인스턴스는 $this 변하기 쉬운. 해당 객체의 현재 상태가 있으며, 부동산이 변하는 (변경)는 해당 인스턴스 (다른 사람이 아닌)를 변경합니다.

메소드가 정적으로 불리는 경우 $this 변하기 쉬운 정의되지 않았습니다. 정적 호출과 관련된 인스턴스가 없기 때문입니다.

여기서 흥미로운 점은 정적 호출이 어떻게 만들어 지는지입니다. 그래서 우리가 주에 어떻게 접근하는지에 대해 이야기합시다.

상태에 접근

이제 우리는 그 상태를 저장 했으므로 액세스해야합니다. 이것은 약간 까다로울 수 있습니다 (또는 방법 비트 이상), 이것을 인스턴스/클래스 외부 (일반 함수 호출 또는 글로벌 범위에서)와 인스턴스/클래스 ( 물체).

인스턴스/클래스 외부에서

인스턴스/클래스 외부에서 우리의 규칙은 매우 간단하고 예측 가능합니다. 인스턴스 또는 클래스 정적을 다루는 경우 각각 두 명의 연산자가 있으며 각각은 즉시 알려줍니다.

  • -> - 객체 운영자 - 인스턴스에 액세스 할 때 항상 사용됩니다.

    $bob = new Person;
    echo $bob->name;
    

    그 전화에 주목하는 것이 중요합니다 Person->foo 의미가 없습니다 (이후 Person 인스턴스가 아닌 클래스입니다). 따라서 이는 구문 분석 오류입니다.

  • :: - 스코프 해상도 운영기 - 이것은 항상 클래스 정적 속성 또는 방법에 액세스하는 데 사용됩니다.

    echo Foo::bar()
    

    또한, 우리는 같은 방식으로 객체의 정적 메소드를 호출 할 수 있습니다.

    echo $foo::bar()
    

    이것의 극도로 우리가 이것을 할 때 주목하는 것이 중요합니다 밖에서, 객체의 인스턴스는에서 숨겨져 있습니다 bar() 방법. 실행과 정확히 동일하다는 것을 의미합니다.

    $class = get_class($foo);
    $class::bar();
    

그러므로, $this 정적 호출에 정의되지 않습니다.

인스턴스/클래스 내부에서

상황이 조금 바뀝니다. 동일한 연산자가 사용되지만 그 의미는 크게 흐려집니다.

그만큼 객체 운영자 -> 여전히 객체의 인스턴스 상태를 호출하는 데 사용됩니다.

class Foo {
    public $a = 1;
    public function bar() {
        return $this->a;
    }
}

전화 bar() 메소드 켜짐 $foo (인스턴스 Foo) 객체 운영기 사용 : $foo->bar() 인스턴스의 버전이 발생합니다 $a.

그것이 우리가 기대하는 방식입니다.

의 의미 :: 운영자는 변경됩니다. 그것은 현재 함수에 대한 호출의 맥락에 따라 다릅니다.

  • 정적 컨텍스트 내에서

    정적 컨텍스트 내에서 사용 된 모든 호출 :: 또한 정적입니다. 예를 살펴 보겠습니다.

    class Foo {
        public function bar() {
            return Foo::baz();
        }
        public function baz() {
            return isset($this);
        }
    }
    

    부름 Foo::bar() 전화 할 것입니다 baz() 정적으로 방법 $this ~ 할 것이다 ~ 아니다 채워집니다. 최근 버전의 PHP (5.3+)에서 이것은 E_STRICT 비 정적 메소드를 정적으로 호출하기 때문에 오류입니다.

  • 인스턴스 컨텍스트 내에서

    반면에 인스턴스 컨텍스트에서 :: 통화 수신기 (우리가 호출하는 메소드)에 따라 다릅니다. 메소드가 정의 된 경우 static, 그러면 정적 호출을 사용합니다. 그렇지 않은 경우 인스턴스 정보를 전달합니다.

    따라서 위의 코드를보고 호출하십시오 $foo->bar() 돌아올 것입니다 true, "정적"호출은 인스턴스 컨텍스트 내에서 발생하기 때문에.

이해가 되나요? 그렇게 생각하지 않았습니다. 혼란 스럽습니다.

단축 키워드

클래스 이름을 사용하여 모든 것을 함께 묶는 것은 다소 더럽기 때문에 PHP는 범위를 쉽게 해결할 수 있도록 3 개의 기본 "바로 가기"키워드를 제공합니다.

  • self - 이것은 현재 클래스 이름을 나타냅니다. 그래서 self::baz() 와 같다 Foo::baz()Foo 클래스 (모든 방법).

  • parent - 이것은 현재 클래스의 부모를 나타냅니다.

  • static - 이것은 호출 클래스를 나타냅니다. 상속 덕분에 어린이 수업은 방법과 정적 특성을 무시할 수 있습니다. 그래서 그것들을 사용한다고 부릅니다 static 클래스 이름 대신 현재 레벨이 아닌 호출이 어디에서 왔는지 해결할 수 있습니다.

이것을 이해하는 가장 쉬운 방법은 몇 가지 예를 살펴 보는 것입니다. 수업을 선택합시다 :

class Person {
    public static $number = 0;
    public $id = 0;
    public function __construct() {
        self::$number++;
        $this->id = self::$number;
    }
    public $name = "";
    public function getName() {
        return $this->name;
    }
    public function getId() {
        return $this->id;
    }
}

class Child extends Person {
    public $age = 0;
    public function __construct($age) {
        $this->age = $age;
        parent::__construct();
    }
    public function getName() {
        return 'child: ' . parent::getName();
    }
}

이제 우리는 여기에서 상속을보고 있습니다. 이것이 나쁜 객체 모델이라는 순간을 무시하지만, 우리가 이것을 가지고 놀 때 어떤 일이 일어나는지 살펴 보겠습니다.

$bob = new Person;
$bob->name = "Bob";
$adam = new Person;
$adam->name = "Adam";
$billy = new Child;
$billy->name = "Billy";
var_dump($bob->getId()); // 1
var_dump($adam->getId()); // 2
var_dump($billy->getId()); // 3

따라서 ID 카운터는 인스턴스와 어린이 모두에서 공유됩니다 (우리가 사용하기 때문에 self 액세스하기 위해. 우리가 사용했다면 static, 우리는 아동 수업에서 그것을 무시할 수 있습니다).

var_dump($bob->getName()); // Bob
var_dump($adam->getName()); // Adam
var_dump($billy->getName()); // child: Billy

우리는 우리가 실행하고 있습니다 Person::getName() 사례 매번 방법. 그러나 우리는 그것을 사용하고 있습니다 parent::getName() 사례 중 하나 (아동 케이스)에서 수행합니다. 이것이이 접근법을 강력하게 만드는 것입니다.

주의 단어 #1

호출 컨텍스트는 인스턴스가 사용되는지 결정하는 것입니다. 그러므로:

class Foo {
    public function isFoo() {
        return $this instanceof Foo;
    }
}

아니다 언제나 진실.

class Bar {
    public function doSomething() {
        return Foo::isFoo();
    }
}
$b = new Bar;
var_dump($b->doSomething()); // bool(false)

지금이야 진짜 여기서 이상해. 우리는 다른 수업을 호출하지만 $this 그것은 그에게 전달됩니다 Foo::isFoo() 메소드는 인스턴스입니다 $bar.

이것은 모든 종류의 버그와 개념적 WTF-ERY를 유발할 수 있습니다. 그래서 나는 피하는 것이 좋습니다 :: 이 세 가지 가상 "바로 컷"키워드를 제외한 모든 인스턴스 메소드의 운영자 (static, self, 그리고 parent).

주의 단어 #2

정적 방법과 속성은 모든 사람이 공유합니다. 그것은 기본적으로 글로벌 변수를 만듭니다. 글로벌과 함께 발생하는 동일한 문제가 있습니다. 그래서 나는 당신이 진정으로 글로벌이라는 것이 편안하지 않으면 정적 방법/속성에 정보를 저장하는 것을 주저 할 것입니다.

주의의 말 #3

일반적으로 사용하여 늦은 정전기 결합으로 알려진 것을 사용하고 싶을 것입니다. static 대신에 self. 그러나 그들은 똑같지 않다는 점에 유의하십시오. "항상 사용하십시오. static 대신에 self 정말 근시안입니다. 대신, 자녀 수업을 무시할 수 있기를 원한다면 생각하고 싶은 전화에 대해 멈추고 생각하십시오. 정적 해결 전화.

TL/DR

너무 나쁘다, 돌아가서 읽어. 너무 길지만 복잡한 주제이기 때문에 길다.

TL/DR #2

알았어 괜찮아. 요컨대, self 참조에 사용됩니다 현재 클래스 이름 수업 내에서 $this 현재 객체를 나타냅니다 사례. 주목하십시오 self 복사/붙여 넣기 단축입니다. 당신은 당신의 클래스 이름으로 안전하게 교체 할 수 있으며, 잘 작동합니다. 하지만 $this 미리 결정할 수없는 동적 변수입니다.

TL/DR #3

객체 운영기를 사용하는 경우 (->), 그럼 당신 언제나 인스턴스를 다루고 있다는 것을 알고 있습니다. 스코프 해소 기능을 사용하는 경우 (::), 당신은 컨텍스트에 대한 자세한 정보가 필요합니다 (우리는 이미 객체 컨텍스트에 있습니까? 우리는 객체 밖에 있습니까? 등).

self (자체가 아님)을 말합니다 유형 수업의 곳 $this 전류를 나타냅니다 사례 수업의. self 정적 멤버 변수에 액세스 할 수 있도록 정적 멤버 함수에 사용됩니다. $this 비 정적 멤버 함수에서 사용되며 멤버 함수가 호출 된 클래스의 인스턴스에 대한 참조입니다.

왜냐하면 this 객체, 당신은 다음과 같이 사용합니다. $this->member

왜냐하면 self 객체가 아니며 기본적으로 현재 클래스를 자동으로 지칭하는 유형입니다. self::member

$this-> 클래스 변수 (멤버 변수) 또는 메소드의 특정 인스턴스를 참조하는 데 사용됩니다.

Example: 
$derek = new Person();

$ Derek은 이제 특정 사례입니다. 모든 사람에게는 First_name과 Last_name이 있지만 $ Derek은 특정 First_name과 Last_name (Derek Martin)을 가지고 있습니다. $ derek 인스턴스 내부에서 우리는 $ this-> first_name 및 $ this-> last_name을 참조 할 수 있습니다.

ClassName ::는 해당 유형의 클래스와 정적 변수 인 정적 메소드를 참조하는 데 사용됩니다. 도움이되면 "static"이라는 단어를 "공유"로 정신적으로 바꿀 수 있습니다. 공유되기 때문에 $ this를 참조 할 수 없으며 특정 인스턴스 (공유되지 않음)를 나타냅니다. 정적 변수 (예 : 정적 $ db_connection)는 객체 유형의 모든 인스턴스에서 공유 할 수 있습니다. 예를 들어, 모든 데이터베이스 개체는 단일 연결 (static $ 연결)을 공유합니다.

정적 변수 예 :단일 멤버 변수가있는 데이터베이스 클래스가있는 척합니다. static $ num_connections; 이제 이것을 생성자에 넣습니다.

function __construct()
{
    if(!isset $num_connections || $num_connections==null)
    {
        $num_connections=0;
    }
    else
    {
        $num_connections++;
    }
}

물체가 생성자를 갖는 것처럼, 또한 소멸자가 있으며, 이는 물체가 죽거나 없을 때 실행됩니다.

function __destruct()
{
    $num_connections--;
}

새 인스턴스를 만들 때마다 연결 카운터를 하나씩 증가시킵니다. 인스턴스 사용을 파괴하거나 중지 할 때마다 연결 카운터가 하나씩 줄어 듭니다. 이러한 방식으로, 우리는 다음과 함께 사용중인 데이터베이스 개체의 인스턴스 수를 모니터링 할 수 있습니다.

echo DB::num_connections;

$ num_connections는 정적 (공유)이므로 총 활성 데이터베이스 개체 수를 반영합니다. 데이터베이스 클래스의 모든 인스턴스 중 데이터베이스 연결을 공유하는 데 사용되는이 기술을 보았을 수 있습니다. 데이터베이스 연결을 만드는 데 시간이 오래 걸리므로 하나만 생성하고 공유하는 것이 가장 좋습니다 (싱글 톤 패턴이라고 함).

정적 메소드 (예 : public static view :: format_phone_number ($ digits))는 이러한 객체 중 하나를 먼저 인스턴스화하지 않고 사용할 수 있습니다 (예 : 내부적으로 $를 참조하지 않습니다).

정적 방법 예 :

public static function prettyName($first_name, $last_name)
{
    echo ucfirst($first_name).' '.ucfirst($last_name);
}

echo Person::prettyName($derek->first_name, $derek->last_name);

보시다시피, 공개 정적 함수 PrettyName은 객체에 대해 아무것도 모릅니다. 객체의 일부가 아닌 일반적인 함수와 같이 전달하는 매개 변수로 작업하고 있습니다. 그렇다면 왜 우리가 물건을 대상의 일부로 가질 수 없다면 귀찮게합니까?

  1. 첫째, 객체에 함수를 첨부하면 물건을 정리하는 데 도움이되므로 어디에서 찾을 수 있는지 알 수 있습니다.
  2. 둘째, 그것은 명명 충돌을 방지합니다. 큰 프로젝트에서는 두 명의 개발자가 getName () 함수를 만들 수있게 될 것입니다. 하나가 className1 :: getName ()을 생성하고 다른 하나는 className2 :: getName ()을 작성하면 전혀 문제가되지 않습니다. 갈등이 없습니다. Yay 정적 방법!

본인::코딩하는 경우 밖의 당신이 참조하려는 정적 메소드가있는 객체는 객체의 이름보기를 사용하여 호출해야합니다 :: format_phone_number ($ phone_number); 코딩하는 경우 내부에 당신이 참조하려는 정적 메소드가있는 객체는 어느 하나 개체의 이름보기 :: format_phone_number ($ pn)를 사용하거나 self :: format_phone_number ($ pn) 단축키를 사용할 수 있습니다.

정적 변수에 대해서도 마찬가지입니다.예시: 보기 :: templates_path 대 셀프 :: templates_path

DB 클래스 내에서 다른 객체의 정적 메소드를 언급 한 경우 객체의 이름을 사용합니다.예시: 세션 :: getUsersonline ();

그러나 DB 클래스가 자체 정적 변수를 언급하고 싶다면 스스로라고 말합니다.예시: 자기 :: 연결;

사물을 정리하는 데 도움이되기를 바랍니다 :)

에서 이 블로그 게시물:

  • self 현재 클래스를 나타냅니다
  • self 정적 함수를 호출하고 정적 멤버 변수를 참조하는 데 사용할 수 있습니다.
  • self 정적 함수 내에서 사용할 수 있습니다
  • self Vtable을 우회하여 다형성 거동을 끄질 수 있습니다.
  • $this 현재 객체를 나타냅니다
  • $this 정적 함수를 호출하는 데 사용할 수 있습니다
  • $this 정적 멤버 변수를 호출하는 데 사용해서는 안됩니다. 사용 self 대신에.
  • $this 정적 함수 내에서는 사용할 수 없습니다

PHP에서는 자체 키워드를 사용하여 정적 특성 및 메소드에 액세스합니다.

문제는 교체 할 수 있다는 것입니다 $this->method() ~와 함께 self::method()어떤 경우에도 method() 정적 여부로 선언됩니다. 그래서 어떤 것을 사용해야합니까?

이 코드를 고려하십시오.

class ParentClass {
    function test() {
        self::who();    // will output 'parent'
        $this->who();   // will output 'child'
    }

    function who() {
        echo 'parent';
    }
}

class ChildClass extends ParentClass {
    function who() {
        echo 'child';
    }
}

$obj = new ChildClass();
$obj->test();

이 예에서 self::who() 항상 '부모'를 출력합니다 $this->who() 객체가 어떤 클래스에 가지고 있는지에 따라 다릅니다.

이제 우리는 자기 자신이 부름을받는 클래스를 말하는 동안 자아를 말할 수 있습니다. $this 참조 현재 객체의 클래스.

따라서, 당신은 언제든지 자기를 사용해야합니다 $this 사용할 수 없거나 후손 클래스가 현재 방법을 덮어 쓰도록 허용하지 않으려는 경우.

클래스 정의 내에서 $ $ 이것은 현재 객체를 나타내고, 자체는 현재 클래스를 나타냅니다.

Self를 사용하여 클래스 요소를 참조하고 $ this를 사용하여 객체 요소를 참조해야합니다.

self::STAT // refer to a constant value
self::$stat // static variable
$this->stat // refer to an object variable  

다음은 비 정적 및 정적 멤버 변수에 대한 $ this 및 자체의 올바른 사용의 예입니다.

<?php
class X {
    private $non_static_member = 1;
    private static $static_member = 2;

    function __construct() {
        echo $this->non_static_member . ' '
           . self::$static_member;
    }
}

new X();
?> 

에 따르면 http://www.php.net/manual/en/language.oop5.static.php 아니요 $self. 만 있습니다 $this, 클래스의 현재 인스턴스 (객체)와 자기를 참조하기 위해 클래스의 정적 멤버를 참조하는 데 사용할 수 있습니다. 객체 인스턴스와 클래스의 차이점은 여기서 진행됩니다.

self 현재 클래스 (라고 불리는),

$this 현재 객체를 나타냅니다. 자기 대신 정적을 사용할 수 있습니다. 예를 참조하십시오 :

    class ParentClass {
            function test() {
                    self::which();  // output 'parent'
                    $this->which(); // output 'child'
            }

            function which() {
                    echo 'parent';
            }
    }

    class ChildClass extends ParentClass {
            function which() {
                    echo 'child';
            }
    }

    $obj = new ChildClass();
    $obj->test();

출력 : 부모의 자녀

  • 객체 포인터 $는 현재 객체를 나타냅니다.
  • 클래스 값 "정적"은 현재 객체를 나타냅니다.
  • 클래스 값 "self"는 정의 된 정확한 클래스를 나타냅니다.
  • 클래스 값 "부모"는 정의 된 정확한 클래스의 부모를 나타냅니다.

과부하를 보여주는 다음 예제를 참조하십시오.

<?php

class A {

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

    public static function newSelfClass()
    {
        return new self;
    }

    public function newThisClass()
    {
        return new $this;
    }
}

class B extends A
{
    public function newParentClass()
    {
        return new parent;
    }
}


$b = new B;

var_dump($b::newStaticClass()); // B
var_dump($b::newSelfClass()); // A because self belongs to "A"
var_dump($b->newThisClass()); // B
var_dump($b->newParentClass()); // A


class C extends B
{
    public static function newSelfClass()
    {
        return new self;
    }
}


$c = new C;

var_dump($c::newStaticClass()); // C
var_dump($c::newSelfClass()); // C because self now points to "C" class
var_dump($c->newThisClass()); // C
var_dump($b->newParentClass()); // A because parent was defined *way back* in class "B"

대부분의 시간은 현재 클래스를 참조하고자하는데 사용하는 이유입니다. static 또는 $this. 그러나 당신이 때가 있습니다 필요 self 무엇이 확장되는지에 관계없이 원래 클래스를 원하기 때문입니다. (매우, 매우 드물다)

여기서 아무도 공연에 대해 이야기하지 않았기 때문에 여기에 내가 한 작은 벤치 마크가 있습니다 (5.6).

 Name     | Time    | Percent  
----------|---------|---------  
 $this->  | 0.99163 | 106.23%  
 self::   | 0.96912 | 103.82%  
 static:: | 0.93348 | 100%

이것이 2,000 000 실행의 결과이며 여기에 내가 사용한 코드가 있습니다.

<?php

require '../vendor/autoload.php';

// My small class to do benchmarks
// All it does is looping over every test x times and record the
//   time it takes using `microtime(true)`
// Then, the percentage is calculated, with 100% being the quickest
// Times are being rouned for outputting only, not to calculate the percentages
$b = new Tleb\Benchmark\Benchmark(2000000);

class Foo
{
    public function calling_this()
    {
        $this->called();
    }

    public function calling_self()
    {
        self::called();
    }

    public function calling_static()
    {
        static::called();
    }

    public static function called()
    {
    }
}

$b->add('$this->',  function () { $foo = new Foo; $foo->calling_this(); });
$b->add('self::',   function () { $foo = new Foo; $foo->calling_self(); });
$b->add('static::', function () { $foo = new Foo; $foo->calling_static(); });

$b->run();

질문은 당신이 전화를 통해 수업의 정적 멤버에게 전화 할 수 있는지 여부가 아니라고 생각합니다. ClassName::staticMember. 질문은 사용의 차이점이었습니다 self::classmember 그리고 $this->classmember.

예를 들어, 다음 두 가지 예 모두 사용하든 오류없이 작동합니다. self:: 또는 $this->

class Person{
    private $name;
    private $address;

    public function __construct($new_name,$new_address){
        $this->name = $new_name;
        $this->address = $new_address;
    }
}

class Person{
    private $name;
    private $address;
    public function __construct($new_name,$new_address){
        self::$name = $new_name;
        self::$address = $new_address;
    }
}

언제 self 다음과 함께 사용됩니다 :: 연산자는 정적 및 비 정적 컨텍스트에서 수행 할 수있는 현재 클래스를 나타냅니다. $this 객체 자체를 나타냅니다. 또한 사용하는 것은 완벽하게 합법적입니다 $this 정적 메소드를 호출하려면 (필드를 참조하지 않음).

$this 현재 클래스 객체를 말하면 self 현재 클래스 (개체가 아님)를 나타냅니다. 클래스는 객체의 청사진입니다. 따라서 클래스를 정의하지만 객체를 구성합니다.

다시 말해, 사용하십시오 self for static 그리고 this for none-static members or methods.

또한 아동/학부모 시나리오에서도 self / parent 주로 아동 및 부모 수업 회원 및 방법을 식별하는 데 사용됩니다.

또한 그 이후로 $this:: 아직 논의되지 않았습니다.

PHP 5.3 기준으로 만 정보의 목적으로, 인스턴스화 된 객체를 처리하여 현재 범위 값을 사용하여 사용하는 것과는 달리 정보를 제공합니다. static::, 대안 적으로 사용할 수 있습니다 $this:: 그렇게 좋아요.

http://ideone.com/7etrhy

class Foo
{
    const NAME = 'Foo';

    //Always Foo::NAME (Foo) due to self
    protected static $staticName = self::NAME;

    public function __construct()
    {
        echo $this::NAME;
    }

    public function getStaticName()
    {
       echo $this::$staticName;
    }
}

class Bar extends Foo
{
    const NAME = 'FooBar';

    /**
     * override getStaticName to output Bar::NAME
     */
    public function getStaticName()
    {
        $this::$staticName = $this::NAME;
        parent::getStaticName();
    }
}

$foo = new Foo; //outputs Foo
$bar = new Bar; //outputs FooBar
$foo->getStaticName(); //outputs Foo
$bar->getStaticName(); //outputs FooBar
$foo->getStaticName(); //outputs FooBar

위의 코드를 사용하는 것은 일반적이거나 권장되는 관행은 아니지만 단순히 사용법을 설명하는 것이며 "알고 있습니까?" 원래 포스터의 질문과 관련하여.

또한 사용을 나타냅니다 $object::CONSTANT 예를 들어 echo $foo::NAME; 반대로 $this::NAME;

나는 같은 질문에 도달했고 간단한 대답은 다음과 같습니다.

  • $ 이것 수업의 인스턴스가 필요합니다
  • 본인:: 그렇지 않습니다

사용할 때마다 정적 방법 또는 정적 속성 그리고 당신이 사용해야하는 수업의 대상이 없으면 그들을 부르고 싶다. 본인:: 그들에게 전화하기 위해 $ 이것 항상 개체에 생성되어야합니다.

사용 self 해당 클래스의 객체/인스턴스를 만들지 않고 클래스 메소드를 호출하려면 저장 (때로는 그 목적을 위해 자기를 사용하십시오). 다시 말해, 실제로 정적으로 방법을 부릅니다. 사용 this 객체 관점.

사례 1 : 사용 self 클래스 상수에 사용할 수 있습니다

 class classA { 
     const FIXED_NUMBER = 4; 
     self::POUNDS_TO_KILOGRAMS
}

수업 밖에서 전화하려면 classA::POUNDS_TO_KILOGRAMS 상수에 액세스하려면

사례 2 : 정적 특성의 경우

class classC {
     public function __construct() { 
     self::$_counter++; $this->num = self::$_counter;
   }
}

Php.net에 따르면이 맥락에는 세 가지 특별한 키워드가 있습니다. self, parent 그리고 static. 클래스 정의 내부에서 속성 또는 메소드에 액세스하는 데 사용됩니다.

$this, 반면에, 해당 클래스에 액세스 할 수있는 한 클래스의 인스턴스와 메소드를 호출하는 데 사용됩니다.

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