답변:
$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()
. 그러나 self :: foo ()를 사용X::foo()
하면 항상 호출됩니다.
에서 http://www.phpbuilder.com/board/showthread.php?t=10354489 :
self
범위 확인 연산자와 함께 사용됩니다 ::
. 정적 및 비 정적 컨텍스트 모두에서 수행 할 수 있습니다. 또한 $this
정적 메소드를 호출하는 데 사용 하는 것이 합법적 이지만 필드를 참조하지는 않습니다.
$this::
?
self 키워드는 정적 멤버로 제한하는 방식이 아닌 '현재 클래스'를 가리키는 것이 아닙니다 . 정적이 아닌 멤버의 컨텍스트 내에서 현재 객체에 대한 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에서 온 괴짜
안녕 Ludwig입니다
sayHello()
$this
포인터를 사용 하므로 vtable이 호출되도록 호출 Geek::getTitle()
됩니다.
sayGoodbye()
를 사용 self::getTitle()
하므로 vtable이 사용되지 않고 Person::getTitle()
호출됩니다. 두 경우 모두 인스턴스화 된 객체의 메서드를 다루며 $this
호출 된 함수 내의 포인터에 액세스 할 수 있습니다.
self
"/ "클래스 정의"와 "객체의 클래스"(실제로 static
) 인 것으로 이해 될 수 있습니다 .
$this::
?
$this::
. 모든 가능한 경우는 이미 더 일반적으로 사용되는 구문으로 덮여 있습니다. 당신이 무슨 뜻인지에 따라, 사용 $this->
, self::
또는 static::
.
DO NOT USE 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::
참조하는 반면 , 클래스는
getStatus
메서드는 클래스가 아닌 클래스 인스턴스를 호출하는 것으로 간주합니다.
self::
, 당신은 더 적은 것을 얻을 수 있습니다 예를 들어 다음과 같이 특정 클래스 이름을 사용하여 혼동 될 수 MyClass::
있습니다.
정말 우리가 우리가 이야기 할 때 무슨 말을하는지 이해하는 데 self
비해 $this
, 우리는 실제로 개념 및 실제적인 수준에 무슨 일이 일어나고 있는지에 파고해야합니다. 나는 실제로 어떤 대답도 적절하게 수행한다고 생각하지 않으므로 여기에 내 시도가 있습니다.
클래스 와 객체 가 무엇인지 이야기하면서 시작하겠습니다 .
그럼, 이다 클래스는 ? 많은 사람들이 그것을 청사진 이나 객체 의 템플릿 으로 정의 합니다. 실제로, 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"
연산자를 사용하여 클래스의 새 인스턴스 를 만듭니다 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;
}
따라서 기본적으로 우리는 정보가 공유되는지 (따라서 정적 인) 아닌지 (그리고 동적)를 식별하는 static 에 대한 "힌트"를 사용하여 클래스와 객체 컨테이너에 정보를 저장합니다 .
메소드 내에서 객체의 인스턴스는 $this
변수 로 표시됩니다 . 해당 객체의 현재 상태가 있으며 속성을 변경 (변경)하면 해당 인스턴스가 변경되지만 다른 인스턴스는 변경되지 않습니다.
메소드가 정적으로 호출되면 $this
변수 가 정의되지 않습니다 . 정적 호출과 연결된 인스턴스가 없기 때문입니다.
여기서 흥미로운 점은 정적 호출 방법입니다. 우리가 상태에 접근하는 방법에 대해 이야기 해 봅시다 :
이제 해당 상태를 저장 했으므로 해당 상태에 액세스해야합니다. 이 비트를 얻을 수있는 까다로운 (또는 방법으로 더 많은 비트 이상), 그래서 두 가지 관점으로이 분할하자 : 인스턴스 / 클래스의 외부에서 (일반 함수 호출에서, 또는 글로벌 범위에서 말하는), 그리고 인스턴스의 내부 / class (객체의 메소드 내에서).
인스턴스 / 클래스 외부에서 우리의 규칙은 매우 간단하고 예측 가능합니다. 우리는 두 개의 연산자를 가지고 있으며 각각 인스턴스 또는 클래스 정적을 처리하고 있는지 즉시 알려줍니다.
->
- 객체 연산자 - 우리는 인스턴스를 액세스하는 경우는 항상 사용됩니다.
$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;
}
}
object-operator를 사용하여 (의 인스턴스 ) 에서 bar()
메소드 호출 :$foo
Foo
$foo->bar()
인스턴스의 버전이 $a
됩니다.
이것이 우리가 기대하는 방식입니다.
::
연산자 의 의미는 변경됩니다. 현재 함수에 대한 호출 컨텍스트에 따라 다릅니다.
정적 컨텍스트 내
정적 컨텍스트에서 사용하는 모든 호출 ::
도 정적입니다. 예를 보자.
class Foo {
public function bar() {
return Foo::baz();
}
public function baz() {
return isset($this);
}
}
호출 Foo::bar()
부르는 것이다 baz()
정적 방법을, 따라서 $this
것입니다 하지 채워. E_STRICT
정적이 아닌 메소드를 정적으로 호출하기 때문에 최신 버전의 PHP (5.3+)에서는 오류가 발생할 수 있습니다.
인스턴스 컨텍스트 내
반면 인스턴스 컨텍스트 내에서 ::
의 수신자 (우리가 호출하는 방법)에 따라 다릅니다. 메소드가로 정의 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()
사례 중 하나 (자식 사례) 에서이 작업을 수행하고 있습니다. 이것이이 접근 방식을 강력하게 만듭니다.
호출 컨텍스트는 인스턴스 사용 여부를 결정합니다. 따라서:
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
).
정적 메서드와 속성은 모든 사람이 공유합니다. 기본적으로 전역 변수가됩니다. 전 세계와 동일한 문제가 있습니다. 따라서 전 세계에 익숙하지 않다면 정적 메서드 / 속성에 정보를 저장하는 것이 정말 주저합니다.
일반적으로을 static
대신 하여 Late-Static-Binding이라는 것을 사용하고 싶을 것입니다 self
. 그러나 그것들은 같은 것이 아니므로 "항상 static
대신에 항상 사용 하는 self
것은 근시안적입니다. "라고 말하고 , 대신하고 싶은 호출에 대해 생각하고 자식 클래스가 정적 해결 을 재정의 할 수 있도록하려면 생각하십시오. 요구.
너무 나쁘고 돌아가서 읽어보십시오. 너무 길지만 복잡한 주제이기 때문에 너무 깁니다.
알았어 괜찮아. 즉, 클래스 내 에서 현재 클래스 이름self
을 참조 하는 데 사용됩니다 . 여기서 as $this
는 현재 객체 인스턴스 를 나타냅니다 . 참고 self
카피는 / 바로 가기를 붙여 넣습니다. 클래스 이름으로 안전하게 바꿀 수 있으며 정상적으로 작동합니다. 그러나$this
미리 결정할 수없는 동적 변수입니다 (클래스가 아닐 수도 있습니다).
객체 연산자가 사용 된 경우 ( ->
) 항상 인스턴스를 처리하고 있다는 것을 알고 있습니다. scope-resolution-operator가 사용되는 경우 ( ::
) 컨텍스트에 대한 추가 정보가 필요합니다 (이미 오브젝트 컨텍스트에 있습니까? 오브젝트 외부에 있습니까? 등).
$this
"엄격한 표준"을 따르고 정적으로 정의되지 않은 메소드를 정적으로 호출하지 않으면 글쎄 ... 정의되지 않습니다. 3v4l.org/WeHVM 동의 한 결과가 이상합니다.
Foo::isFoo()
정적으로 호출 $this
되므로 정의되지 않습니다. 내 의견으로는 더 직관적 인 행동입니다. - 에서 확장 된다면 다른 결과 가 나옵니다 . 그런 다음 호출 은 실제로 인스턴스 컨텍스트 내에 있습니다 (PHP7에만 해당되지 않음). Bar
Foo
Foo::isFoo()
$this->
클래스 변수 (멤버 변수) 또는 메서드의 특정 인스턴스를 나타내는 데 사용됩니다.
Example:
$derek = new Person();
$ derek은 이제 Person의 특정 인스턴스입니다. 모든 Person은 first_name과 last_name을 가지고 있지만 $ derek은 특정한 first_name과 last_name을 가지고 있습니다 (Derek Martin). $ derek 인스턴스 내에서 $ this-> first_name 및 $ this-> last_name으로 참조 할 수 있습니다.
ClassName ::은 해당 유형의 클래스와 정적 변수 인 정적 메서드를 나타내는 데 사용됩니다. 도움이되면 정신적으로 "정적"이라는 단어를 "공유"로 바꿀 수 있습니다. 공유되어 있기 때문에 특정 인스턴스 (공유되지 않음)를 나타내는 $ this를 참조 할 수 없습니다. 정적 변수 (정적 $ db_connection)는 객체 유형의 모든 인스턴스간에 공유 될 수 있습니다. 예를 들어 모든 데이터베이스 개체는 단일 연결 (정적 $ connection)을 공유합니다.
정적 변수 예 : 단일 멤버 변수가있는 데이터베이스 클래스가 있다고 가정합니다. 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))는 먼저 해당 오브젝트 중 하나를 인스턴스화하지 않고 사용할 수 있습니다 (즉, 내부적으로 $ this를 참조하지 않음).
정적 방법 예 :
public static function prettyName($first_name, $last_name)
{
echo ucfirst($first_name).' '.ucfirst($last_name);
}
echo Person::prettyName($derek->first_name, $derek->last_name);
보다시피 public static 함수 prettyName은 객체에 대해 아무것도 모른다. 객체의 일부가 아닌 일반 함수처럼 전달하는 매개 변수로 작업하고 있습니다. 그렇다면 왜 우리가 물건의 일부로 그것을 가질 수 없다면 왜 귀찮게합니까?
SELF :: 참조하려는 정적 메소드가있는 오브젝트 외부 에서 코딩 하는 경우 오브젝트 이름을 사용하여 호출해야합니다. View :: format_phone_number ($ phone_number); 당신이 코딩하는 경우 안에 당신이 있습니다, 참조 할 정적 메서드가있는 객체 중 하나를 오브젝트의 이름보기 :: format_phone_number ($ PN)를 사용, 또는 셀프 :: format_phone_number ($ PN)를 사용할 수 있습니다를 바로 가기
정적 변수도 마찬가지입니다. 예 : View :: templates_path와 self :: templates_path
DB 클래스 내에서 다른 객체의 정적 메서드를 참조하는 경우 객체 이름을 사용합니다. 예 : Session :: getUsersOnline ();
그러나 DB 클래스가 자체 정적 변수를 참조하려면 self라고 말하면됩니다. 예 : self :: connection;
희망을 정리하는 데 도움이되기를 바랍니다 :)
$
부호 를 사용해야한다는 것을 지적하고 싶습니다 . 예를 들어self::$templates_path
PHP에서는 self 키워드를 사용하여 정적 속성 및 메서드에 액세스합니다.
문제는 당신이 대체 할 수 있다는 것입니다 $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()
항상 'parent'를 출력하지만 $this->who()
객체의 클래스에 따라 다릅니다.
이제 self는 자신이 호출 $this
된 클래스를 참조하고 현재 객체 의 클래스 를 참조 함을 알 수 있습니다.
따라서, $this
사용할 수 없거나 자손 클래스가 현재 메소드를 겹쳐 쓰지 못하게하려는 경우 에만 self를 사용해야합니다 .
에 따르면 http://www.php.net/manual/en/language.oop5.static.php 전혀 없다 $self
. 단지이 $this
클래스의 정적 멤버를 참조하는 데 사용할 수있는 클래스 (객체), 자기의 현재 인스턴스 참조를 들어,. 객체 인스턴스와 클래스의 차이점이 여기에 있습니다.
나는 전화로 클래스의 정적 멤버를 호출 할 수 있는지 여부는 질문이 아니라고 생각합니다 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;
}
}
Fatal error: Access to undeclared static property: Person::$name in D:\LAMP\www\test.php on line 16
self
현재 클래스 (호출 된 클래스)를 나타냅니다.
$this
현재 객체를 나타냅니다. self 대신 static을 사용할 수 있습니다. 예를보십시오 :
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();
출력 : 부모 자식
$this
는 현재 객체를 나타냅니다.static
은 현재 객체를 나타냅니다.self
은 정의 된 정확한 클래스를 나타냅니다.parent
은 정의 된 정확한 클래스의 부모를 나타냅니다.과부하를 보여주는 다음 예를 참조하십시오.
<?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();
1 / 2e9 s = 0.5 ns
오늘날의 상황입니다.
use
키워드 tbh를 사용하지 않은 이유를 모르겠지만 더 이상 벤치 마크를 다시 실행할 PHP가 없으며 다시 설치하고 싶지는 않습니다.
또한 $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의 경우 정적 멤버, 메서드 및 함수를 호출 할 수 없습니다.
당신이 사용할 수있는 자체 :: 다른 클래스 및 액세스 정적 멤버, 방법 및 상수 키워드를. $ this 키워드의 경우 부모 클래스에서 확장 될 때와 동일 합니다. 부모 클래스에서 확장 될 때 다른 클래스의 비 정적 멤버, 메서드 및 함수에 액세스 할 수 있습니다.
아래 코드는 self :: 및 $ this 키워드 의 예입니다 . 코드 파일에 코드를 복사하여 붙여 넣고 출력을 확인하십시오.
class cars{
var $doors=4;
static $car_wheel=4;
public function car_features(){
echo $this->doors." Doors <br>";
echo self::$car_wheel." Wheels <br>";
}
}
class spec extends cars{
function car_spec(){
print(self::$car_wheel." Doors <br>");
print($this->doors." Wheels <br>");
}
}
/********Parent class output*********/
$car = new cars;
print_r($car->car_features());
echo "------------------------<br>";
/********Extend class from another class output**********/
$car_spec_show=new spec;
print($car_spec_show->car_spec());