Kada naudoti save per šį?

PHP 5 yra skirtumas tarp self ir $this ?

Kada kiekvienas tinka?

1788 m
30 сент. Casey Watson 30 iš rugsėjo. 2008-09-30 09:23 '08 9:23 am. 2008-09-30 09:23
@ 22 atsakymai

Trumpas atsakymas

Jei norite nurodyti dabartinį objektą, naudokite $this . Naudokite self kad nurodytumėte dabartinę klasę. Kitaip tariant, naudokite $this->member ne statiniams elementams, statiniams elementams naudokite self::$member .

Visas atsakymas

Toliau pateikiamas tinkamo $this ir self naudojimo pavyzdys ne statiniams ir statiniams nario kintamiesiems:

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

Toliau pateikiamas netinkamų ir statinių narių kintamųjų netinkamo $this ir self naudojimo pavyzdys:

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

Čia yra pavyzdys apie polimorfizmą su $this nario funkcijomis:

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

Čia yra pavyzdys, kaip slopinti polimorfinį elgesį su self narių funkcijoms:

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

Idėja yra ta, kad $this->foo() kviečia nario funkciją foo() ką> funkcija - tikslaus dabartinio objekto tipo. Jei objektas turi type X , tai> skambina X::foo() . Jei objekto vertė yra type Y , ji vadina Y::foo() . Bet s> self :: foo (), X::foo() visada vadinamas.

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

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

1519
30 сент. John Millikin atsakymas rugsėjo 30 d 2008-09-30 09:29 '08 at 9:29 2008-09-30 09:29

Raktinio žodžio „savarankiškai“ NEGALIMA tik „dabartinei klasei“, bent jau ne tokiu būdu, kuris apribotų jus statiniais nariais. Ne statinio nario kontekste self taip pat suteikia galimybę apeiti dabartinį objektą „vtable“ ( žr. „Wiki“ ), kaip tik jūs galite naudoti parent::methodName() kad paskambintumėte pagrindinę funkcijos versiją, todėl galite skambinti „ self::methodName() skambinti dabartiniam metodo įgyvendinimui.

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

Tai bus:

border=0

Sveiki, aš esu Ludwig geek
Goodbye Ludwig Man

sayHello() naudoja $this rodiklį, todėl vtable yra vadinamas paskambinti Geek::getTitle() . sayGoodbye() naudoja self::getTitle() , todėl vtable nenaudojamas ir jį vadina Person::getTitle() . Abiem atvejais susiduriame su egzemplioriaus objekto metodu ir turime prieigą prie $this rodiklio funkcijose, kurios vadinamos.

712
27 июля '09 в 21:00 2009-07-27 21:00 atsakymą pateikė „ nbeagle “ liepos 27 d. 09 val. 21:00 2009-07-27 21:00

NENAUDOKITE self:: , naudokite static::

Yra dar vienas aspektas: verta paminėti. Klaidingai, self:: reiškia taikymo sritį apibrėžimo taške, kuris nėra vykdymo vietoje . Apsvarstykite šią paprastą klasę dviem būdais:

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

Jei vadiname „ Person::status() , pamatysime, kad „Žmogus yra gyvas“. Dabar apsvarstykite, kas atsitinka, kai sukuriame klasę, kuri paveldi iš šios:

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

Skambinimas Deceased::status() tikimės matyti „Asmuo yra miręs“, tačiau matome, kad „Asmuo yra gyvas“, nes srityje yra pirminio metodo apibrėžimas, kai paskambino į self::getStatus() .

PHP 5.3 turi sprendimą. static:: skiriamosios gebos operatorius įgyvendina „pavėluotą statinį įrišimą“, kuris yra išgalvotas būdas pasakyti, kad jis yra susijęs su klasės apimtimi. Pakeiskite status() į static::getStatus() o rezultatai yra tai, ko tikitės. Senesnėse PHP versijose jums reikės rasti kludge.

Žr. PHP dokumentaciją .

Todėl, norėdami atsakyti į klausimą, ne klausimą ...

$this-> reiškia dabartinį objektą (klasės egzempliorių), o static:: reiškia klasę

429
24 июля '11 в 18:08 2011-07-24 18:08 atsakymas pateikiamas Sqoo liepos 24 d., 11 val. 18:08 2011-07-24 18:08

Norint iš tikrųjų suprasti, apie ką kalbame, kai kalbame apie self , tai reikia iš tiesų įsivaizduoti, kas vyksta konceptualiu ir praktiniu lygmeniu. Aš tikrai nemanau, kad atsakymai į tai atitiktų, todėl čia yra mano bandymas.

Pradėkite pokalbį apie tai, kas yra klasė ir objektas.

Klasės ir objektai, konceptualiai

Taigi, kas yra klasė? Daugelis žmonių jį apibrėžia kaip objekto planą ar šabloną. Iš tiesų čia galite skaityti daugiau apie PHP klases . Ir tam tikru mastu tai iš tikrųjų yra. Pažvelkite į klasę:

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

Kaip galite pasakyti, šioje klasėje yra turto $name ir metodas (funkcija), vadinamas sayHello() .

Labai svarbu pažymėti, kad klasė yra statinė struktūra. Tai reiškia, kad Person klasė, apibrėžta, visada yra ta pati, kai žiūrite į ją.

Kita vertus, objektas vadinamas klasės egzemplioriumi. Tai reiškia, kad mes imamės šios klasės „plano“ ir panaudosime dinaminę kopiją. Ši kopija dabar yra konkrečiai susieta su kintamuoju, kuriame jis saugomas. Todėl bet kokie pavyzdžių pakeitimai yra vietiniai šiuo atveju.

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

Naudodami new operatorių sukuriame naujus klasės egzempliorius.

Todėl sakome, kad klasė yra pasaulinė struktūra, o objektas yra vietinė struktūra. Nesijaudinkite dėl šios juokingos sintaksės -> šiek tiek apie tai kalbėsime.

Kitas dalykas, apie kurį turime kalbėti, yra tai, kad mes galime patikrinti, ar instancijos instanceof konkreti klasė: $bob instanceof Person , kuris grąžina loginę vertę, jei egzempliorius $bob buvo sukurtas naudojant Person klasę arba vaiko elementą .

Valstybės apibrėžimas

Taigi leiskite šiek tiek išsiaiškinti, kas yra klasėje. Yra 5 „dalykų“ tipai, kuriuos klasė turi:

  • Savybės Pagalvokite apie tai kaip kintamuosius, kuriuos kiekvienas egzempliorius laikys.

     class Foo { public $bar = 1; } 
  • Statinės savybės. Pagalvokite apie tai kaip kintamuosius, kurie dalijami klasės lygmeniu. Tai reiškia, kad jie niekada nekopijuojami kiekvieną kopiją.

     class Foo { public static $bar = 1; } 
  • Metodai yra funkcijos, kurias kiekvienoje instancijoje bus (ir dirbti su egzemplioriais).

     class Foo { public function bar() {} } 
  • Statiniai metodai. Tai yra funkcijos, kurios dalijamos visoje klasėje. Jie neveikia, bet galioja tik statinės savybės.

     class Foo { public static function bar() {} } 
  • Konstansai - išspręstų klasių konstantai. Nesileiskite čia giliai, bet pridėkite išsamumą:

     class Foo { const BAR = 1; } 

Taigi, saugome informaciją apie klasės ir objekto konteinerius statiniais patarimais, kurie nustato, ar informacija yra viešai prieinama (taigi ir statinė), ar ne (ir todėl dinamiška).

Sąlyga ir metodai

Šio metodo viduje objekto pavyzdį vaizduoja $this kintamasis. Esama dabartinė šio objekto būsena, o bet kokio turto pasikeitimas (pakeitimas) sukels pasikeitimą šiuo atveju (bet ne kitiems).

Jei metodas vadinamas statiniu, $this kintamasis yra neapibrėžtas. Taip yra dėl to, kad nėra statinio skambučio.

Įdomu, kaip sukuriami statiniai skambučiai. Taigi kalbėkime apie tai, kaip mes pasiekiame valstybę:

Prieiga prie valstybės

Taigi dabar, kai išsaugojome šią būseną, turime ją pasiekti. Tai gali būti šiek tiek paini (ar daugiau nei šiek tiek), todėl padalinkime jį į du aspektus: iš išorės iš egzemplioriaus / klasės (pvz., Iš įprastos funkcijos skambučio arba iš pasaulinės apimties) ir egzemplioriaus / klasės viduje (nuo objekto metodo).

Iš išorės ribų

Išskyrus atvejį / klasę, mūsų taisyklės yra gana paprastos ir nuspėjamos. Turime du teiginius, ir kiekvienas iš jų nedelsdamas praneša mums, ar kalbame apie egzempliorių ar statinę klasę:

  • -> - objekto operatorius - tai visada naudojama, kai pasiekiame egzempliorių.

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

    Svarbu pažymėti, kad skambinant Person Person->foo nėra prasmės (nes Person yra klasė, o ne pavyzdys). Todėl tai yra analizavimo klaida.

  • :: - taikymo srities rezoliucija-operatorius - tai visada naudojama norint pasiekti statinį turtą arba klasės metodą.

     echo Foo::bar() 

    Be to, mes galime skambinti statiniu metodu objektui tokiu pačiu būdu:

     echo $foo::bar() 

    Labai svarbu pažymėti, kad kai tai darome iš išorės , objekto pavyzdys yra paslėptas nuo bar() metodo. Tai reiškia, kad jis yra toks pats, kaip jis veikia:

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

Todėl $this nėra apibrėžta statiniame kvietime.

Vidinė instancija / klasė

Daiktai šiek tiek keičiasi. Naudojami tie patys operatoriai, tačiau jų reikšmė tampa žymiai neryškesnė.

Objekto operatorius -> vis dar naudojamas skambinti į objekto egzemplioriaus būseną.

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

Skambinant bar() metodu $foo ( Foo atvejis), naudojant operatoriaus objektą: $foo->bar() atsiras pavyzdžio $a versija.

Taigi, kaip tikimės.

Operatoriaus vertės pokyčiai. Tai priklauso nuo dabartinio funkcijų skambučio konteksto:

  • Statiniame kontekste

    Statiniame kontekste visi skambučiai su :: taip pat bus statiniai. Apsvarstykite pavyzdį:

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

    Skambinimas „ Foo::bar() statiniu būdu vadins baz() metodą, todėl $this nebus užpildytas. Verta pažymėti, kad pastarosiose PHP versijose (5,3+) tai sukels E_STRICT klaidą, nes mes statiškai nustatome E_STRICT metodus.

  • Nagrinėjant bylą

    Antra vertus, skambučiai naudojant :: priklauso nuo skambučio gavėjo (mūsų vadinamo metodo). Jei metodas apibrėžiamas kaip static , tada jis naudoja statinį skambutį. Jei ne, ji siunčia informaciją apie egzempliorių.

    Taigi, įvertinus pirmiau minėtą kodą, skambutis į $foo->bar() grįžta true , nes „statinis“ skambutis vyksta konteksto kontekste.

Turite prasmę? Aš nemaniau. Tai paini.

Trumpalaikiai raktiniai žodžiai

Kadangi susiejimas viskas kartu naudojant klasės pavadinimus yra gana nepatogus, PHP suteikia 3 pagrindinius „sparčiuosius“ žodžius, kad palengvintų domeno rezoliuciją.

  • self - Tai reiškia dabartinį klasės pavadinimą. Taigi, self::baz() sutampa su Foo::baz() klasėje Foo (bet kokiu metodu).

  • parent - tai reiškia dabartinės klasės tėvą.

  • static - tai reiškia, kad klasė vadinama. Dėl paveldėjimo vaiko klasės gali ignoruoti metodus ir statines savybes. Todėl skambinant juos static o ne klasės pavadinimu, galime nuspręsti, iš kur skambinama, o ne dabartiniu lygiu.

Pavyzdžiai

Paprasčiausias būdas tai suprasti yra pradėti mokytis kai kurių pavyzdžių. Pasirinkite klasę:

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

Dabar mes taip pat žiūrime į paveldėjimą. Nedelsdami ignoruokite, kad tai yra blogas objekto modelis, tačiau pažiūrėkime, kas atsitiks, kai žaidžiame su juo:

 $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 

Tokiu būdu ID skaitiklis naudojamas abiem atvejais ir vaikams (nes mes jį naudojame, kad galėtume ją pasiekti. Jei mes naudojome static , galėtume jį iš naujo apibrėžti vaikų klasėje).

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

Atkreipkite dėmesį, kad kiekvieną kartą vykdome egzemplioriaus Person::getName() metodą. Tačiau mes naudojame parent::getName() kad tai atliktume viename iš atvejų (vaiko registras). Tai daro šį požiūrį galingą.

Atsargumo žodis # 1

Atminkite, kad skambinantis kontekstas nustato, ar egzempliorius naudojamas. Todėl:

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

Ne visada tiesa.

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

Dabar tai tikrai keista. Mes vadiname kitą klasę, bet $this , kuris perduodamas Foo::isFoo() metodui, yra $bar pavyzdys.

Tai gali sukelti visų rūšių klaidas ir konceptualų WTF-ery. Todėl primygtinai rekomenduoju vengti :: operatoriaus iš visų metodų visuose, išskyrus tris virtualius „trumpus sutrumpintus“ raktinius žodžius ( static , self ir parent ).

Atsargumo žodis # 2

Atkreipkite dėmesį, kad statiniai metodai ir savybės yra visiems bendrinami. Dėl to jie dažniausiai yra pasauliniai kintamieji. Su visomis tokiomis pačiomis problemomis kaip ir pasaulis. Todėl labai nesugebėsiu saugoti informacijos statiniuose metoduose / savybėse, jei jums tai nepatinka, tai tikrai pasaulinė.

3 atsargumo žodis

Apskritai, jūs norite naudoti tai, kas vadinama „Late-Static-Binding“, naudojant static o ne self . Tačiau atkreipkite dėmesį, kad jie nėra tie patys dalykai, todėl „visada naudokite static o ne self tikrai trumparegiškas. Vietoj to, sustokite ir pagalvokite apie skambutį, kurį norite padaryti, ir pagalvokite, ar norite, kad vaiko klasės galėtų pakeisti šį statinį leidžiamas skambutis

Tl / dr

Per blogai, grįžkite ir skaitykite. Tai gali būti per ilgas, bet taip ilgai, nes tai yra sudėtinga tema.

TL / DR # 2

Geras, puikus. Trumpai tariant, self naudojamasi, norint nurodyti klasėje esantį dabartinį klasės pavadinimą, kur $this reiškia dabartinį objekto pavyzdį. Atkreipkite dėmesį, kad self yra nukopijuoti / įklijuoti. Jūs galite saugiai jį pakeisti savo klasės pavadinimu, ir jis veiks gerai. Bet $this yra dinamiškas kintamasis, kuris negali būti iš anksto nustatytas (ir net negali būti jūsų klasė).

TL / DR # 3

Jei naudojate objekto operatorių ( -> ), visada žinote, kad susiduriate su pavyzdžiu. Jei naudojate raiškos operatorių ( :: , jums reikia papildomos informacijos apie kontekstą (ar mes jau turime objekto kontekstą? Ar mes iš objekto? Ir tt).

229
10 июня '13 в 18:21 2013-06-10 18:21 atsakymas pateikiamas ircmaxell birželio 10 d. 13 val. 21:21 2013-06-10 18:21

self (ne „$ self“) reiškia klasės tipą, kur $this reiškia dabartinį klasės egzempliorių. self skirtas naudoti statinėse narių funkcijose, kad galėtumėte pasiekti statinius nario kintamuosius. $this naudojama ne statiniams nario funkcijoms ir yra nuoroda į klasės, kuriai buvo paskirta nario funkcija, egzempliorių.

Kadangi this yra objektas, jį naudokite kaip: $this->member

Kadangi self nėra objektas, tai iš esmės yra tipas, kuris automatiškai nurodo dabartinę klasę, jūs jį naudojate kaip: self::member

109
30 сент. Atsakymas pateikiamas M.Zebra rugsėjo 30 d 2008-09-30 10:26 '08 10:26 am. 2008-09-30 10:26

$this-> naudojamas konkrečiam klasės kintamųjų (narių kintamųjų) ar metodų žymėjimui.

 Example: $derek = new Person(); 

$ derek dabar yra specifinis Asmens pavyzdys. Kiekvienas asmuo turi pirmojo vardo ir paskutinio_pavadinimo vardą, tačiau $ derek turi konkretų vardą ir vardą (Derek Martin). „$ Derek“ egzemplioriaus viduje galime nurodyti juos kaip $ this-> first_name ir $ this-> last_name

ClassName :: naudojamas šio tipo klasėms ir statiniams kintamiesiems, statiniams metodams žymėti. Jei tai padeda, galite protiškai pakeisti žodį „statinis“ „įprastu“. Kadangi jie yra bendrinami, jie negali nurodyti „$ this“, o tai reiškia konkretų atvejį (nesidalijamu). Statinius kintamuosius (ty statinį $ db_connection) galima bendrinti tarp visų objekto tipo atvejų. Pavyzdžiui, visi duomenų bazės objektai naudoja vieną ryšį (statinis ryšys $).

Statiniai kintamieji Pavyzdys: Įsivaizduokite, kad mes turime duomenų bazės klasę su vienu nario kintamuoju: statinis $ num_connections; Dabar įdėkite jį į konstruktorių:

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

Kaip ir objektai turi konstruktorių, jie taip pat turi destruktorių, kurie įvykdomi, kai objektas miršta arba neveikia:

 function __destruct() { $num_connections--; } 

Kiekvieną kartą kurdami naują instanciją, jis padidins ryšio skaičių vienu. Kiekvieną kartą, kai mes sunaikinsime ar nustojame naudoti egzempliorių, jis sumažina ryšio skaičių vienu. Taigi galime stebėti naudojamo duomenų bazės objekto atvejų skaičių:

 echo DB::num_connections; 

Kadangi $ num_connections yra statinis (bendras), bus rodomas bendras aktyvių duomenų bazės objektų skaičius. Galbūt jūs matėte šį metodą, naudojamą bendrai naudoti duomenų bazės ryšius tarp visų duomenų bazės klasės atvejų. Tai daroma todėl, kad kuriant duomenų bazės ryšį užtrunka daug laiko, todėl geriausia yra sukurti tik vieną ir bendrinti (tai vadinama „Singleton“ šablonu).

Statiniai metodai (t. Y. Vieši statiniai rodiniai :: format_phone_number ($ digit)) gali būti naudojami be vieno iš šių objektų pirmosios instancijos (t.y., jie viduje nenurodo $ this).

Statinio metodo pavyzdys:

 public static function prettyName($first_name, $last_name) { echo ucfirst($first_name).' '.ucfirst($last_name); } echo Person::prettyName($derek->first_name, $derek->last_name); 

Kaip matote, vieša statinė funkcija, gražiName, nieko nežino apie objektą. Jis tiesiog veikia su parametrais, kuriuos perduodate kaip įprastą funkciją, kuri nėra objekto dalis. Kodėl nerimauti, jei galėtume tik tai ne kaip objekto dalį?

  1. Pirma, privalomosios objektų funkcijos padeda jums organizuoti dalykus, todėl žinote, kur jas rasti.
  2. Antra, tai užkerta kelią vardų konfliktams. Dideliame projekte galite turėti du kūrėjus, kurie sukuria „getName“ () funkcijas. Jei sukuriate ClassName1 :: getName (), o kitas sukuria ClassName2 :: getName (), tai visai nėra problema. Nėra konflikto. Yay statiniai metodai!

SELF :: Jei užkoduojate už objekto, turinčio statinį metodą, kurį norite pasiekti, turite jį skambinti naudodami objekto pavadinimą View :: format_phone_number ($ phone_number); Если вы кодируете внутри объекта, у которого есть статический метод, к которому вы хотите обратиться, вы можете либо использовать имя объекта View :: format_phone_number ($ pn), либо вы можете использовать ярлык self :: format_phone_number ($ pn)

То же самое касается статических переменных: Пример: View :: templates_path versus self :: templates_path

Внутри класса DB, если бы мы ссылались на статический метод какого-либо другого объекта, мы использовали бы имя объекта: Example: Session :: getUsersOnline();

Но если класс DB хотел ссылаться на свою собственную статическую переменную, он просто сказал бы себя: Пример: self :: connection;