문제
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 가지 유형의 "사물"이 있습니다.
속성 -이를 각 인스턴스에 포함 할 변수로 생각하십시오.
class Foo { public $bar = 1; }
정적 특성 -이를 클래스 수준에서 공유하는 변수로 생각하십시오. 각 인스턴스에 의해 복사되지 않음을 의미합니다.
class Foo { public static $bar = 1; }
행동 양식 - 각 인스턴스에 포함 할 함수 (및 인스턴스에서 작동).
class Foo { public function bar() {} }
정적 방법 -이 기능은 전체 클래스에서 공유되는 기능입니다. 그들이하다 ~ 아니다 인스턴스에서만 작동하지만 대신 정적 특성에서만 작동합니다.
class Foo { public static function bar() {} }
상수 - 클래스 해결 상수. 여기에 더 깊이 가지 않고 완전성을 추가합니다.
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은 객체에 대해 아무것도 모릅니다. 객체의 일부가 아닌 일반적인 함수와 같이 전달하는 매개 변수로 작업하고 있습니다. 그렇다면 왜 우리가 물건을 대상의 일부로 가질 수 없다면 귀찮게합니까?
- 첫째, 객체에 함수를 첨부하면 물건을 정리하는 데 도움이되므로 어디에서 찾을 수 있는지 알 수 있습니다.
- 둘째, 그것은 명명 충돌을 방지합니다. 큰 프로젝트에서는 두 명의 개발자가 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::
그렇게 좋아요.
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
, 반면에, 해당 클래스에 액세스 할 수있는 한 클래스의 인스턴스와 메소드를 호출하는 데 사용됩니다.