etc./StackOverFlow

언제 '$this'보다 'self'를 사용해야 합니까?

청렴결백한 만능 재주꾼 2021. 12. 8. 01:19
반응형

질문자 :Casey Watson


self$this 의 차이점은 무엇입니까?

각각 언제가 적절한가요?



짧은 답변

$this 를 사용하여 현재 개체를 참조하십시오. self 를 사용하여 현재 클래스를 참조하십시오. 즉, $this->member 를 사용하고 정적 멤버의 경우 self::$member 를 사용합니다.

전체 답변

다음은 비정적 및 정적 멤버 변수에 대해 $thisself 를 올바르게 사용하는 예입니다.

 <?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(); ?>

다음은 비정적 및 정적 멤버 변수에 대해 $thisself 를 잘못 사용하는 예입니다.

 <?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에서 :

작성자: http://board.phpbuilder.com/member.php?145249-laserlight


John Millikin

키워드 자체가 이상하지 않는 방법으로, '현재 클래스'에 불과 참조하지 않는 정적 멤버로 제한합니다 당신을. 비정적 멤버의 컨텍스트 내에서 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의 작별 인사

sayHello()$this 포인터를 사용하므로 vtable은 Geek::getTitle() 호출하기 위해 호출됩니다. sayGoodbye()self::getTitle() 을 사용하므로 vtable 은 사용하지 않고 Person::getTitle() 을 호출합니다. 두 경우 모두, 우리는 인스턴스화된 객체의 메소드를 다루고 있으며 호출된 함수 내에서 $this


nbeagle

self:: 사용하지 마십시오 . static:: 사용 :: *

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

 class Person { public static function status() { self::getStatus(); } protected static function getStatus() { echo "Person is alive"; } }

Person::status() 호출하면 "Person is live" 가 표시됩니다. 이제 다음에서 상속하는 클래스를 만들 때 어떤 일이 발생하는지 고려하십시오.

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

Deceased::status() 호출하면 "사람이 사망했습니다"가 표시될 것으로 예상됩니다. self::getStatus() 호출이 정의될 때 범위에 원래 메서드 정의가 포함되어 있으므로 "Person is live"가 표시됩니다.

PHP 5.3에는 솔루션이 있습니다. static:: resolution 연산자는 호출된 클래스의 범위에 바인딩된다는 멋진 방법인 "late static binding"을 구현합니다. status() 의 행을 static::getStatus() 변경하면 예상한 결과가 됩니다. 이전 버전의 PHP에서는 이를 수행하기 위해 kludge를 찾아야 합니다.

PHP 문서 참조

그래서 질문이 아닌 질문에 대답하려면 ...

$this-> 는 현재 객체(클래스의 인스턴스)를 static:: 은 클래스를 참조합니다.


Sqoo

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 연산자를 사용하여 클래스의 새 인스턴스를 만듭니다.

따라서 Class는 전역 구조이고 Object는 지역 구조라고 합니다. -> 구문에 대해 걱정하지 마십시오. 잠시 후에 이에 대해 알아보겠습니다.

우리가에 대한 이야기해야 하나 다른 점은 인스턴스가있는 경우 우리가 확인할 수 있다는 것입니다 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 변수 가 정의되지 않습니다 . 정적 호출과 연결된 인스턴스가 없기 때문입니다.

여기서 흥미로운 점은 정적 호출이 수행되는 방식입니다. 상태에 액세스하는 방법에 대해 이야기해 보겠습니다.

상태 액세스

이제 해당 상태를 저장했으므로 액세스해야 합니다. 이 비트를 얻을 수있는 까다로운 (이상 조금보다 훨씬), 그래서 두 가지 관점으로이 분할하자 : 인스턴스 / 클래스의 외부에서 (일반 함수 호출에서, 또는 글로벌 범위에서 말하는), 그리고 인스턴스의 내부 /class(객체의 메서드 내에서).

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

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

  • -> - object-operator - 인스턴스에 액세스할 때 항상 사용됩니다.

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

    Person->foo 를 호출하는 것은 의미가 없다는 점에 유의하는 것이 중요합니다 Person 은 인스턴스가 아니라 클래스이기 때문에). 따라서 이는 구문 분석 오류입니다.

  • :: - scope-resolution-operator - 이것은 항상 Class 정적 속성 또는 메서드에 액세스하는 데 사용됩니다.

     echo Foo::bar()

    또한 동일한 방식으로 객체에 대한 정적 메서드를 호출할 수 있습니다.

     echo $foo::bar()

    외부 에서 이 작업을 수행할 때 객체의 인스턴스가 bar() 메서드 에서 숨겨져 있다는 점에 유의하는 것이 매우 중요합니다. 실행하는 것과 정확히 동일하다는 것을 의미합니다.

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

따라서 $this 는 정적 호출에서 정의되지 않습니다.

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

여기서 상황이 조금 바뀝니다. 동일한 연산자가 사용되지만 그 의미가 상당히 흐려집니다.

object-operator -> 는 여전히 개체의 인스턴스 상태를 호출하는 데 사용됩니다.

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

object-operator: $foo->bar() $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 클래스(위의 모든 메서드) 내의 Foo::baz() 와 동일합니다.

  • 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)

이제 여기가 정말 이상합니다. 다른 클래스를 호출하고 있지만 Foo::isFoo() 메서드에 전달 $this $bar 의 인스턴스입니다.

이것은 모든 종류의 버그와 개념적 WTF-ery를 유발할 수 있습니다. 따라서 세 가지 가상 "단축키" 키워드( static , selfparent )를 :: 연산자를 피하는 것이 좋습니다.

주의사항 #2

정적 메서드와 속성은 모든 사람이 공유합니다. 그것은 그것들을 기본적으로 전역 변수로 만듭니다. 전역과 함께 오는 모든 동일한 문제와 함께. 따라서 진정한 전역 정보가 마음에 들지 않는 한 정적 메서드/속성에 정보를 저장하는 것을 매우 주저할 것입니다.

주의사항 #3

self static 을 사용하여 Late-Static-Binding이라고 하는 것을 사용하고 싶을 것입니다. 그러나 그것들은 같은 것이 아니므로 "항상 self static 사용하는 것은 근시안적입니다. 대신에 멈추고 원하는 호출에 대해 생각하고 자식 클래스가 이를 재정의할 수 있기를 원하는지 생각하십시오. 정적 해결 호출.

TL/DR

아쉽지만 돌아가서 읽어보세요. 너무 길 수 있지만 복잡한 주제이기 때문에 너무 깁니다.

TL/DR #2

알았어 괜찮아. 간단히 말해서 self 는 클래스 내에서 현재 클래스 이름 을 참조하는 데 사용됩니다. 여기서 $this 는 현재 개체 인스턴스를 참조합니다. self 는 복사/붙여넣기 단축키입니다. 클래스 이름으로 안전하게 바꿀 수 있으며 잘 작동합니다. 그러나 $this 는 미리 결정할 수 없는 동적 변수입니다(그리고 당신의 클래스가 아닐 수도 있습니다).

TL/DR #3

객체 연산자가 사용되면( -> ) 항상 인스턴스를 다루고 있다는 것을 알 수 있습니다. scope-resolution-operator가 사용되는 경우( :: ) 컨텍스트에 대한 추가 정보가 필요합니다(이미 객체 컨텍스트에 있습니까? 객체 외부에 있습니까? 등).


ircmaxell

self ($self 아님)는 클래스 의 유형 을 참조하는 $this 는 클래스 의 현재 인스턴스를 나타냅니다. self 는 정적 멤버 변수에 액세스할 수 있도록 정적 멤버 함수에서 사용하기 위한 것입니다. $this 는 비정적 멤버 함수에서 사용되며 멤버 함수가 호출된 클래스의 인스턴스에 대한 참조입니다.

this 객체이기 때문에 $this->member 와 같이 사용합니다.

self 는 객체가 아니기 때문에 기본적으로 현재 클래스를 자동으로 참조하는 유형입니다. 다음과 같이 사용합니다. self::member


MrZebra

$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를 참조할 수 없습니다. 정적 변수(예: static $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은 객체에 대해 아무것도 모릅니다. 객체의 일부가 아닌 일반 함수처럼 전달한 매개변수로 작업하는 것입니다. 그렇다면 객체의 일부가 아닌 것으로만 가질 수 있다면 왜 귀찮게 할까요?

  1. 첫째, 객체에 기능을 추가하면 물건을 정리하는 데 도움이 되므로 어디에서 찾을 수 있는지 알 수 있습니다.
  2. 둘째, 이름 충돌을 방지합니다. 큰 프로젝트에서는 두 명의 개발자가 getName() 함수를 생성하게 될 것입니다. 하나는 ClassName1::getName()을 만들고 다른 하나는 ClassName2::getName()을 생성하면 전혀 문제가 되지 않습니다. 충돌이 없습니다. 예, 정적 메서드입니다!

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;

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


lo_fye

이 블로그 게시물에서 :

  • self 는 현재 클래스를 참조합니다.
  • self 는 정적 함수를 호출하고 정적 멤버 변수를 참조하는 데 사용할 수 있습니다.
  • self 는 정적 함수 내에서 사용할 수 있습니다.
  • self 는 vtable을 우회하여 다형성 동작을 끌 수도 있습니다.
  • $this 는 현재 개체를 나타냅니다.
  • $this 는 정적 함수를 호출하는 데 사용할 수 있습니다.
  • $this 는 정적 멤버 변수를 호출하는 데 사용하면 안 됩니다. 대신 self 를 사용하십시오.
  • $this 는 정적 함수 내에서 사용할 수 없습니다.

okconfused

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

method() 가 정적으로 선언되었는지 여부에 관계없이 어디에서나 $this->method()self::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를 사용해야 합니다.


ramin rostami

클래스 정의 내에서 $this 는 현재 객체를 self 는 현재 클래스를 참조합니다.

self 사용하여 class 요소를 $this 사용하여 object 요소를 참조해야 합니다.

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

Tarun Singhal

다음은 비정적 및 정적 멤버 변수에 대해 $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(); ?>

Mohit Bumb

Static Keyword 에 따르면 $self 가 없습니다. 클래스의 현재 인스턴스(객체)를 참조하기 위한 $this 와 클래스의 정적 멤버를 참조하는 데 사용할 수 있는 self 여기서 객체 인스턴스와 클래스의 차이점이 작용합니다.


cruizer

  • 개체 포인터 $this 는 현재 개체를 참조합니다.
  • 클래스 값 static 은 현재 개체를 참조합니다.
  • 클래스 값 self 는 그것이 정의된 정확한 클래스를 참조합니다.
  • 클래스 값 parent는 그것이 정의된 정확한 클래스의 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 가 필요할 때가 있습니다. (매우, 아주 드물게)


Xeoncross

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; } }

dr evil

self 는 현재 클래스(호출된 클래스)를 참조합니다.

$this 는 현재 개체를 나타냅니다. self 대신 static을 사용할 수 있습니다.

예를 참조하십시오.

 class ParentClass { function test() { self::which(); // Outputs 'parent' $this->which(); // Outputs 'child' } function which() { echo 'parent'; } } class ChildClass extends ParentClass { function which() { echo 'child'; } } $obj = new ChildClass(); $obj->test();

산출:

 parent child

Kabir Hossain

다음은 작은 벤치마크입니다( repl.it 의 7.2.24 ).

 Speed (in seconds) Percentage $this-> 0.91760206222534 100 self:: 1.0047659873962 109.49909865716 static:: 0.98066782951355 106.87288857386

4 000 000 실행에 대한 결과입니다. 결론: 상관없습니다. 다음은 내가 사용한 코드입니다.

 <?php class Foo { public function calling_this() { $this->called(); } public function calling_self() { self::called(); } public function calling_static() { static::called(); } public static function called() {} } $foo = new Foo(); $n = 4000000; $times = []; // warmup for ($i = 0; $i < $n; $i++) { $foo->calling_this(); } for ($i = 0; $i < $n; $i++) { $foo->calling_self(); } for ($i = 0; $i < $n; $i++) { $foo->calling_static(); } $start = microtime(true); for ($i = 0; $i < $n; $i++) { $foo->calling_this(); } $times["this"] = microtime(true)-$start; $start = microtime(true); for ($i = 0; $i < $n; $i++) { $foo->calling_self(); } $times["self"] = microtime(true)-$start; $start = microtime(true); for ($i = 0; $i < $n; $i++) { $foo->calling_static(); } $times["static"] = microtime(true)-$start; $min = min($times); echo $times["this"] . "\t" . ($times["this"] / $min)*100 . "\n"; echo $times["self"] . "\t" . ($times["self"] / $min)*100 . "\n"; echo $times["static"] . "\t" . ($times["static"] / $min)*100 . "\n";

tleb

self :: 연산자와 함께 사용되면 정적 및 비정적 컨텍스트 모두에서 수행할 수 있는 현재 클래스를 참조합니다. $this 는 개체 자체를 나타냅니다. $this 를 사용하여 정적 메서드를 호출하는 것은 완전히 합법적입니다(필드를 참조하는 것은 아님).


mrDjouk

나는 같은 질문에 부딪쳤고 간단한 대답은 다음과 같습니다.

  • $this 는 클래스의 인스턴스가 필요합니다
  • self:: 하지 않습니다

정적 메서드정적 속성 을 사용하고 클래스의 개체를 인스턴스화하지 않고 호출하려는 경우 $this 항상 개체를 생성해야 하기 때문에 호출 self:


Mike

$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; 과 대조적으로;


Will B.

$this 는 현재 클래스 객체를 self 는 현재 클래스(객체 아님)를 참조합니다. 클래스는 객체의 청사진입니다. 따라서 클래스를 정의하지만 객체를 구성합니다.

즉, self for static this for none-static members or methods .

또한 자식/부모 시나리오에서 self / parent 는 주로 자식 및 부모 클래스 멤버와 메서드를 식별하는 데 사용됩니다.


Rakesh Singh

사용 self 당신이 이렇게 절약, 그 클래스의 객체 / 인스턴스를 생성하지 않고 클래스의 메소드를 호출 할 경우 RAM은 (때로는 그 목적 자체를 사용). 즉, 실제로는 정적으로 메서드를 호출하고 있습니다. 객체 관점에 this 사용하십시오.


Minhaj

사례 1: self 사용할 수 있습니다.

 클래스 클래스 { 
     상수 FIXED_NUMBER = 4; 
     자기::POUNDS_TO_KILOGRAMS
}

클래스 외부에서 호출하려면 classA::POUNDS_TO_KILOGRAMS 를 사용하여 상수에 액세스하십시오.

사례 2: 정적 속성의 경우

클래스 클래스 C {
     공개 함수 __construct() { 
     자기::$_counter++; $this->num = self::$_counter;
   }
}

li bing zhao

php.net에 따르면 이 컨텍스트에는 self , parentstatic 세 가지 특수 키워드가 있습니다. 클래스 정의 내부에서 속성이나 메서드에 액세스하는 데 사용됩니다.

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


Fil

self:: 현재 클래스에 사용되는 키워드이며 기본적으로 정적 멤버, 메서드 및 상수에 액세스하는 데 사용됩니다. 그러나 $this 의 경우 정적 멤버, 메서드 및 함수를 호출할 수 없습니다.

다른 클래스에서 self:: 키워드를 사용하고 정적 멤버, 메서드 및 상수에 액세스할 수 있습니다. 언제 부모 클래스에서 확장될 것이며 $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());

Deepak Syal

출처 : http:www.stackoverflow.com/questions/151969/when-should-i-use-self-over-this

반응형