Saya akan bertanya apa perbedaan antara: cont A; $ this-> A and self :: A
timmz
Jawaban:
1728
Jawaban singkat
Gunakan $thisuntuk merujuk ke objek saat ini. Gunakan selfuntuk merujuk ke kelas saat ini. Dengan kata lain, gunakan
$this->memberuntuk anggota non-statis, gunakan self::$memberuntuk anggota statis.
Jawaban Lengkap
Berikut adalah contoh penggunaan yang benar dari $thisdan selfuntuk variabel anggota yang tidak statis dan statis:
<?php
class X {private $non_static_member =1;privatestatic $static_member =2;function __construct(){
echo $this->non_static_member .' '.self::$static_member;}}new X();?>
Berikut ini adalah contoh penggunaan salah$this dan selfuntuk variabel anggota tidak-statis dan statis:
<?php
class X {private $non_static_member =1;privatestatic $static_member =2;function __construct(){
echo self::$non_static_member .' '. $this->static_member;}}new X();?>
Berikut adalah contoh polimorfisme dengan $thisuntuk fungsi anggota:
<?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();?>
Berikut adalah contoh menekan perilaku polimorfik dengan menggunakan selfuntuk fungsi anggota:
<?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();?>
Idenya adalah yang $this->foo()memanggil foo()fungsi anggota dari apa pun jenis yang tepat dari objek saat ini. Jika objeknya adalah type X, ia memanggil X::foo(). Jika objeknya adalah type Y, ia memanggil Y::foo(). Tetapi dengan self :: foo (), X::foo()selalu dipanggil.
Jawaban ini terlalu sederhana. Seperti yang ditunjukkan dalam jawaban lain, selfdigunakan dengan operator resolusi lingkup ::untuk merujuk ke kelas saat ini; ini dapat dilakukan dalam konteks statis dan non-statis. Selain itu, sangat sah untuk digunakan $thisuntuk memanggil metode statis (tetapi tidak untuk bidang referensi).
Artefacto
50
Juga pertimbangkan untuk menggunakan static :: bukannya :: self jika Anda menggunakan 5.3+. Itu bisa menyebabkan Anda sakit kepala yang tidak terhitung, lihat jawaban saya di bawah ini untuk alasannya.
Sqoo
25
-1. Jawaban ini menyesatkan, baca jawaban lain untuk info lebih lanjut.
Pacerier
6
Ini mungkin terlalu disederhanakan, tetapi itu menjawab pertanyaan tingkat dasar saya tanpa membuat kepala saya meledak. Saya memang mendapatkan lebih banyak informasi yang saya temukan membantu lebih jauh ke bawah, tetapi untuk sekarang saya hanya mencoba mencari tahu mengapa saya menekan atribut kelas saya dengan $ this-> attrib dan konstanta kelas dengan self :: konstan. Ini membantu saya memahami hal itu dengan lebih baik
MydKnight
Bagaimana dengan $this::?
James
742
Kata kunci sendiri TIDAK merujuk hanya ke 'kelas saat ini', setidaknya tidak dengan cara yang membatasi Anda untuk anggota statis. Dalam konteks anggota non-statis, selfjuga menyediakan cara untuk melewati vtable ( lihat wiki pada vtable ) untuk objek saat ini. Sama seperti yang dapat Anda gunakan parent::methodName()untuk memanggil versi orang tua dari suatu fungsi, sehingga Anda dapat menelepon self::methodName()untuk memanggil implementasi metode saat ini di kelas.
Halo, saya Ludwig si pecandu
Selamat tinggal dari Ludwig, orang itu
sayHello()menggunakan $thispointer, sehingga vtable dipanggil untuk memanggil Geek::getTitle().
sayGoodbye()menggunakan self::getTitle(), jadi vtable tidak digunakan, dan Person::getTitle()dipanggil. Dalam kedua kasus, kita berhadapan dengan metode objek yang dipakai, dan memiliki akses ke $thispointer dalam fungsi yang disebut.
Jawaban ini akan lebih baik jika Anda mulai dengan aturan umum daripada pengecualian. Ini masalah gaya, bukan keahlian teknis. Ini adalah contoh terbaik yang pernah saya lihat tentang perbedaan antara self :: dan $ this->, tetapi memalukan untuk menyembunyikannya dengan menyangkal gagasan terlebih dahulu.
adjwilli
3
@adjwilli: Mengapa itu gaya buruk? Tidakkah hal itu meningkatkan kesadaran jika harapan (tesis) OP pertama kali ditolak (antitesis) dan kemudian penjelasannya diberikan sebagai sintesis?
hakre
1
Saya menemukan "kelas saat ini" benar-benar bermasalah. Karena kata kombinasi dapat dipahami sebagai "kelas di mana selfterletak" / "definisi kelas itu adalah bagian literal dari" serta "kelas objek" (yang sebenarnya akan menjadi static).
Jakumi
Bagaimana dengan $this::?
James
1
@ James - tidak ada alasan untuk menggunakan $this::; semua kemungkinan kasus sudah dicakup oleh sintaksis yang lebih umum digunakan. Tergantung pada apa yang Anda maksud, penggunaan $this->, self::atau static::.
ToolmakerSteve
461
JANGAN GUNAKAN self::, gunakanstatic::
Ada aspek lain dari diri :: yang layak disebut. Mengganggu self::mengacu pada ruang lingkup pada titik definisi bukan pada titik eksekusi . Pertimbangkan kelas sederhana ini dengan dua metode:
classPerson{publicstaticfunction status(){self::getStatus();}protectedstaticfunction getStatus(){
echo "Person is alive";}}
Jika kita memanggil Person::status()kita akan melihat "Orang itu hidup". Sekarang pertimbangkan apa yang terjadi ketika kita membuat kelas yang mewarisi dari ini:
classDeceasedextendsPerson{protectedstaticfunction getStatus(){
echo "Person is deceased";}}
Memanggil Deceased::status()kita akan berharap untuk melihat "Orang sudah meninggal" namun apa yang kita lihat adalah "Orang itu hidup" karena ruang lingkup berisi definisi metode asli ketika panggilan ke self::getStatus()didefinisikan.
PHP 5.3 punya solusinya. yang static::menerapkan Operator resolusi "terlambat statis mengikat" yang merupakan cara mewah untuk mengatakan bahwa itu terikat pada lingkup kelas yang disebut. Ubah baris status()menjadi static::getStatus()dan hasilnya adalah apa yang Anda harapkan. Dalam versi PHP yang lebih lama, Anda harus menemukan kludge untuk melakukan ini.
"Memanggil Almarhum :: status () kami berharap akan melihat" Orang telah meninggal "". Tidak. Ini adalah panggilan fungsi statis sehingga tidak ada polimorfisme yang terlibat.
cquezel
2
Dari semua kekurangan PHP, saya tidak berpikir ini gila sama sekali. Bagaimana lagi mereka mengizinkan coders untuk menunjuk metode pada kelas saat ini (sebagai lawan melihat mereka di vtable)? Jika mereka menamainya secara berbeda (mungkin dengan menggarisbawahi garis depan) maka orang yang menginginkan fitur ini akan mengkritiknya karena jelek. Selain itu, apa pun nama waras yang mungkin mereka gunakan tampaknya akan selalu ada orang yang mudah bingung yang akan mengkritiknya karena perilaku "gila", mungkin tidak menyadari bagaimana metode pengiriman bahkan bekerja.
mentega
2
Contohnya kelihatannya membingungkan bagi saya: Saya melihat getStatusmetode sebagai metode yang saya sebut contoh kelas, bukan kelas.
Jānis Elmeris
1
@ Sqoo - mengatakan "JANGAN GUNAKAN diri ::, gunakan static ::" adalah poin aneh untuk dibuat - itu sengaja bukan operasi yang sama. Saya pikir poin yang Anda benar-benar buat adalah "lebih jelas jika Anda menggunakan nama kelas aktual 'MyClass ::', daripada 'self ::' . Artinya, jika Anda ingin perilaku self::, Anda bisa mendapatkan itu, kurang membingungkan, dengan menggunakan nama kelas tertentu, mis MyClass::.
ToolmakerSteve
248
Untuk benar-benar memahami apa yang kita bicarakan ketika kita berbicara tentang selflawan $this, kita harus benar-benar menggali apa yang terjadi pada tingkat konseptual dan praktis. Saya benar-benar tidak merasakan jawaban melakukan hal ini dengan tepat, jadi inilah usaha saya.
Mari kita mulai dengan berbicara tentang apa kelas dan objek itu.
Kelas Dan Objek, Secara Konseptual
Jadi, apa adalah sebuah kelas ? Banyak orang mendefinisikannya sebagai cetak biru atau templat untuk suatu objek. Bahkan, Anda dapat membaca lebih lanjut Tentang Kelas Di PHP Di Sini . Dan sampai batas tertentu itulah sebenarnya. Mari kita lihat sebuah kelas:
Seperti yang Anda tahu, ada properti di kelas yang dipanggil $namedan metode (fungsi) dipanggil sayHello().
Ini sangat penting untuk dicatat bahwa kelas adalah struktur statis. Yang berarti bahwa kelas Person, setelah didefinisikan, selalu sama di mana pun Anda melihatnya.
Objek di sisi lain adalah apa yang disebut turunan Kelas. Artinya adalah bahwa kita mengambil "cetak biru" kelas, dan menggunakannya untuk membuat salinan yang dinamis. Salinan ini sekarang secara khusus terkait dengan variabel tempat penyimpanannya. Oleh karena itu, setiap perubahan pada instance adalah lokal untuk instance tersebut.
$bob =newPerson;
$adam =newPerson;
$bob->name ='Bob';
echo $adam->name;// "my name"
Kami membuat instance baru kelas menggunakan newoperator.
Oleh karena itu, kita katakan bahwa Kelas adalah struktur global, dan Obyek adalah struktur lokal. Jangan khawatir tentang ->sintaks lucu itu , kita akan membahasnya sedikit lagi.
Satu hal lain yang harus kita bicarakan, adalah bahwa kita dapat memeriksa apakah instance adalah instanceofkelas tertentu: $bob instanceof Personyang mengembalikan boolean jika $bobinstance dibuat menggunakan Personkelas, atau anak dari Person.
Mendefinisikan Negara
Jadi mari kita gali sedikit ke dalam apa yang sebenarnya mengandung kelas Ada 5 jenis "hal" yang dikandung kelas:
Properti - Pikirkan ini sebagai variabel yang akan berisi setiap instance.
classFoo{public $bar =1;}
Properti Statis - Pikirkan ini sebagai variabel yang dibagikan di tingkat kelas. Berarti mereka tidak pernah disalin oleh setiap contoh.
classFoo{publicstatic $bar =1;}
Metode - Ini adalah fungsi yang masing-masing instance akan berisi (dan beroperasi pada instance).
classFoo{publicfunction bar(){}}
Metode Statis - Ini adalah fungsi yang dibagikan di seluruh kelas. Mereka tidak beroperasi pada instance, melainkan pada properti statis saja.
classFoo{publicstaticfunction bar(){}}
Konstanta - Konstanta yang diselesaikan kelas. Tidak masuk lebih dalam di sini, tetapi menambahkan untuk kelengkapan:
classFoo{const BAR =1;}
Jadi pada dasarnya, kami menyimpan informasi pada kelas dan objek kontainer menggunakan "petunjuk" tentang statis yang mengidentifikasi apakah informasi tersebut dibagikan (dan karenanya statis) atau tidak (dan karenanya dinamis).
Negara dan Metode
Di dalam suatu metode, instance objek diwakili oleh $thisvariabel. Keadaan saat objek itu ada di sana, dan bermutasi (mengubah) properti apa pun akan menghasilkan perubahan ke instance itu (tetapi tidak yang lain).
Jika suatu metode disebut secara statis, $thisvariabel tidak didefinisikan . Ini karena tidak ada instance yang terkait dengan panggilan statis.
Yang menarik di sini adalah bagaimana panggilan statis dibuat. Jadi mari kita bicara tentang bagaimana kita mengakses negara:
Mengakses negara
Jadi sekarang kita telah menyimpan status itu, kita perlu mengaksesnya. Ini bisa menjadi sedikit rumit (atau jauh lebih sedikit), jadi mari kita bagi menjadi dua sudut pandang: dari luar instance / kelas (katakanlah dari pemanggilan fungsi normal, atau dari lingkup global), dan di dalam instance / class (dari dalam metode pada objek).
Dari Luar Instance / Kelas
Dari luar instance / kelas, aturan kami cukup sederhana dan dapat diprediksi. Kami memiliki dua operator, dan masing-masing memberi tahu kami segera jika kami berurusan dengan instance atau static kelas:
->- object-operator - Ini selalu digunakan ketika kita mengakses instance.
$bob =newPerson;
echo $bob->name;
Penting untuk dicatat bahwa panggilan Person->footidak masuk akal (karena Personkelas, bukan instance). Oleh karena itu, itu adalah kesalahan parse.
::- scope-resolution-operator - Ini selalu digunakan untuk mengakses properti atau metode statis Class.
echo Foo::bar()
Selain itu, kita dapat memanggil metode statis pada objek dengan cara yang sama:
echo $foo::bar()
Ini sangat penting untuk dicatat bahwa ketika kita melakukan ini dari luar , misalnya objek tersembunyi dari bar()metode. Artinya sama persis dengan menjalankan:
$class = get_class($foo);
$class::bar();
Karena itu, $thistidak didefinisikan dalam panggilan statis.
Dari Inside Of An Instance / Class
Banyak hal berubah di sini. Operator yang sama digunakan, tetapi artinya menjadi kabur secara signifikan.
Operator objek-> masih digunakan untuk melakukan panggilan ke keadaan instance objek.
Memanggil Foo::bar()akan memanggil baz()metode statis, dan karenanya $thisakan tidak diisi. Perlu dicatat bahwa dalam versi PHP terbaru (5.3+) ini akan memicu E_STRICTkesalahan, karena kami memanggil metode non-statis secara statis.
Dalam konteks instance
Di dalam konteks instance di sisi lain, panggilan yang dibuat menggunakan ::tergantung pada penerima panggilan (metode yang kami panggil). Jika metode ini didefinisikan static, maka akan menggunakan panggilan statis. Jika tidak, itu akan meneruskan informasi instan.
Jadi, melihat kode di atas, panggilan $foo->bar()akan kembali true, karena panggilan "statis" terjadi di dalam konteks instance.
Masuk akal? Tidak mengira begitu. Ini membingungkan.
Kata kunci pintas
Karena mengikat semuanya bersama-sama menggunakan nama kelas agak kotor, PHP menyediakan 3 kata kunci "jalan pintas" dasar untuk mempermudah penyelesaian ruang lingkup.
self- Ini merujuk pada nama kelas saat ini. Jadi self::baz()sama dengan Foo::baz()di dalam Fookelas (metode apa pun di atasnya).
parent - Ini merujuk pada induk dari kelas saat ini.
static- Ini mengacu pada kelas yang dipanggil. Berkat warisan, kelas anak dapat menimpa metode dan properti statis. Jadi memanggil mereka menggunakan staticbukan nama kelas memungkinkan kita untuk menyelesaikan dari mana panggilan itu berasal, daripada tingkat saat ini.
Contohnya
Cara termudah untuk memahami ini adalah mulai melihat beberapa contoh. Mari pilih kelas:
Sekarang, kami juga melihat warisan di sini. Abaikan sejenak bahwa ini adalah model objek yang buruk, tetapi mari kita lihat apa yang terjadi ketika kita bermain dengan ini:
Jadi penghitung ID dibagikan di seluruh instance dan anak-anak (karena kami menggunakan selfuntuk mengaksesnya. Jika kami menggunakannya static, kami bisa menimpanya dalam kelas anak).
var_dump($bob->getName());// Bob
var_dump($adam->getName());// Adam
var_dump($billy->getName());// child: Billy
Perhatikan bahwa kami menjalankan metode Person::getName()instance setiap waktu. Tapi kami menggunakan parent::getName()untuk melakukannya di salah satu kasus (kasus anak). Inilah yang membuat pendekatan ini kuat.
Perhatian # 1
Perhatikan bahwa konteks panggilan adalah yang menentukan apakah instance digunakan. Karena itu:
Sekarang benar - benar aneh di sini. Kami memanggil kelas yang berbeda, tetapi $thisyang diteruskan ke Foo::isFoo()metode adalah turunan dari $bar.
Ini dapat menyebabkan semua jenis bug dan WTF-ery konseptual. Jadi saya akan sangat menyarankan menghindari ::operator dari dalam metode instan pada apa pun kecuali yang tiga virtual "short-cut" kata kunci ( static, self, dan parent).
Perhatian # 2
Perhatikan bahwa metode dan properti statis dibagikan oleh semua orang. Itu membuat mereka pada dasarnya variabel global. Dengan semua masalah yang sama dengan global. Jadi saya akan benar-benar ragu untuk menyimpan informasi dalam metode / properti statis kecuali Anda merasa nyaman dengan itu menjadi benar-benar global.
Perhatian # 3
Secara umum, Anda ingin menggunakan apa yang dikenal sebagai Late-Static-Binding dengan menggunakan staticalih-alih self. Tetapi perhatikan bahwa mereka bukan hal yang sama, jadi mengatakan "selalu gunakan staticbukannya selfbenar-benar picik. Sebaliknya, berhenti dan pikirkan tentang panggilan yang ingin Anda buat dan pikirkan jika Anda ingin kelas anak-anak dapat menimpa statis yang diselesaikan panggilan.
TL / DR
Sayang sekali, kembali dan baca. Mungkin terlalu lama, tapi itu lama karena ini adalah topik yang kompleks
TL / DR # 2
Baiklah. Singkatnya, selfdigunakan untuk mereferensikan nama kelas saat ini di dalam kelas, di mana $thismerujuk pada instance objek saat ini . Perhatikan bahwa itu selfadalah jalan pintas salin / tempel. Anda dapat dengan aman menggantinya dengan nama kelas Anda, dan itu akan berfungsi dengan baik. Tetapi $thisadalah variabel dinamis yang tidak dapat ditentukan sebelumnya (dan mungkin bahkan bukan kelas Anda).
TL / DR # 3
Jika objek-operator digunakan ( ->), maka Anda selalu tahu Anda berurusan dengan sebuah instance. Jika lingkup-resolusi-operator digunakan ( ::), Anda memerlukan informasi lebih lanjut tentang konteksnya (apakah kita sudah berada dalam konteks objek? Apakah kita berada di luar objek? Dll).
Word of Caution # 1: $ this tidak akan didefinisikan saat memanggil metode statis: 3v4l.org/9kr0e
Mark Achée
Yah ... $thistidak akan ditentukan jika Anda mengikuti "Standar Ketat" dan jangan panggil metode statis yang tidak didefinisikan sebagai statis. Saya melihat hasil yang Anda jelaskan di sini: 3v4l.org/WeHVM Setuju, sangat aneh.
Mark Achée
2
Setelah membaca deskripsi panjangnya sepenuhnya, saya merasa malas untuk menggulir ke atas lagi untuk meningkatkannya. Hanya bercanda, saya benar-benar membuatnya jengkel: D. Terima kasih ini sangat bermanfaat.
Mr_Green
3
alangkah baiknya untuk menambahkan penjelasan yang jelas tentang perbedaan antara self :: $ property dan self :: property; Saya pikir itu cukup membingungkan juga
Tommaso Barbugli
1
WoC # 1 berperilaku berbeda sejak PHP 7. Seperti Foo::isFoo()disebut statis, $thistidak akan didefinisikan. Itu perilaku yang lebih intuitif menurut saya. - Hasil lain yang berbeda diberikan jika Bardiperpanjang dari Foo. Maka panggilan Foo::isFoo()akan benar-benar berada dalam konteks instance (tidak spesifik untuk PHP7).
Kontrollfreak
117
self(bukan $ self) mengacu pada jenis kelas, di mana seperti $thismerujuk pada instance kelas saat ini. selfdigunakan untuk fungsi anggota statis untuk memungkinkan Anda mengakses variabel anggota statis. $thisdigunakan dalam fungsi anggota yang tidak statis, dan merupakan referensi ke instance dari kelas di mana fungsi anggota dipanggil.
Karena thisadalah sebuah objek, Anda menggunakannya seperti:$this->member
Karena selfbukan objek, itu pada dasarnya adalah tipe yang secara otomatis merujuk ke kelas saat ini, Anda menggunakannya seperti:self::member
$this-> digunakan untuk merujuk pada instance spesifik dari variabel kelas (variabel anggota) atau metode.
Example:
$derek =newPerson();
$ derek sekarang adalah contoh spesifik dari Person. Setiap Orang memiliki nama depan dan nama belakang, tetapi $ derek memiliki nama depan dan nama belakang tertentu (Derek Martin). Di dalam instance $ derek, kita dapat merujuknya sebagai $ this-> first_name dan $ this-> last_name
ClassName :: digunakan untuk merujuk pada tipe kelas itu, dan variabel statisnya, metode statis. Jika ini membantu, Anda dapat secara mental mengganti kata "statis" dengan "dibagikan". Karena dibagikan, mereka tidak dapat merujuk ke $ this, yang merujuk pada contoh spesifik (tidak dibagikan). Variabel Statis (mis. $ Db_connection statis) dapat dibagi di antara semua instance dari jenis objek. Sebagai contoh, semua objek database berbagi satu koneksi (koneksi $ statis).
Variabel Statis Contoh:
Berpura-pura kita memiliki kelas basis data dengan variabel anggota tunggal: static $ num_connections; Sekarang, letakkan ini di konstruktor:
function __construct(){if(!isset $num_connections || $num_connections==null){
$num_connections=0;}else{
$num_connections++;}}
Sama seperti objek memiliki konstruktor, mereka juga memiliki destruktor, yang dieksekusi ketika objek mati atau tidak disetel:
function __destruct(){
$num_connections--;}
Setiap kali kita membuat instance baru, penghitung koneksi kita akan bertambah satu. Setiap kali kita menghancurkan atau berhenti menggunakan instance, itu akan mengurangi penghitung koneksi satu per satu. Dengan cara ini, kita dapat memonitor jumlah instance dari objek database yang telah kita gunakan dengan:
echo DB::num_connections;
Karena $ num_connections bersifat statis (dibagi-pakai), ia akan mencerminkan jumlah total objek database aktif. Anda mungkin telah melihat teknik ini digunakan untuk berbagi koneksi database di antara semua instance dari kelas database. Ini dilakukan karena membuat koneksi database membutuhkan waktu lama, jadi yang terbaik untuk membuatnya hanya satu, dan membaginya (ini disebut Pola Singleton).
Metode Statis (yaitu public static View :: format_phone_number ($ digit)) dapat digunakan TANPA pertama-tama instantiating salah satu objek tersebut (yaitu Mereka tidak merujuk secara internal ke $ this).
Seperti yang Anda lihat, fungsi statis publik prettyName tidak tahu apa-apa tentang objek. Ini hanya bekerja dengan parameter yang Anda lewati, seperti fungsi normal yang bukan bagian dari objek. Lalu, mengapa repot-repot, kalau saja kita tidak memilikinya sebagai bagian dari objek?
Pertama, melampirkan fungsi ke objek membantu Anda mengatur berbagai hal, sehingga Anda tahu di mana menemukannya.
Kedua, ini mencegah konflik penamaan. Dalam proyek besar, Anda cenderung memiliki dua pengembang membuat fungsi getName (). Jika satu membuat ClassName1 :: getName (), dan yang lain membuat ClassName2 :: getName (), tidak ada masalah sama sekali. Tidak ada konflik. Yay metode statis!
DIRI ::
Jika Anda melakukan pengkodean di luar objek yang memiliki metode statis yang ingin Anda rujuk, Anda harus memanggilnya menggunakan nama objek View :: format_phone_number ($ phone_number); Jika Anda mengkode di dalam objek yang memiliki metode statis yang ingin Anda lihat, Anda bisa melakukannya menggunakan objek nama View :: format_phone_number ($ pn), ATAU Anda dapat menggunakan self :: format_phone_number ($ pn) shortcut
Hal yang sama berlaku untuk variabel statis:
Contoh: Lihat :: templates_path versus self :: templates_path
Di dalam kelas DB, jika kita merujuk pada metode statis dari beberapa objek lain, kita akan menggunakan nama objek:
Contoh: Session :: getUsersOnline ();
Tetapi jika kelas DB ingin merujuk ke variabel statisnya sendiri, ia hanya akan mengatakan sendiri:
Contoh: self :: connection;
Di PHP, Anda menggunakan kata kunci mandiri untuk mengakses properti dan metode statis.
Masalahnya adalah Anda dapat mengganti $this->method()dengan self::method()mana saja, terlepas dari apakah method()dinyatakan statis atau tidak. Jadi yang mana yang harus Anda gunakan?
Pertimbangkan kode ini:
classParentClass{function test(){self::who();// will output 'parent'
$this->who();// will output 'child'}function who(){
echo 'parent';}}classChildClassextendsParentClass{function who(){
echo 'child';}}
$obj =newChildClass();
$obj->test();
Dalam contoh ini, self::who()akan selalu menampilkan 'induk', sementara $this->who()akan bergantung pada kelas apa yang dimiliki objek.
Sekarang kita dapat melihat bahwa diri merujuk ke kelas yang disebutnya, sementara $thismengacu pada kelas objek saat ini .
Jadi, Anda harus menggunakan diri sendiri saat $this tidak tersedia, atau ketika Anda tidak ingin mengizinkan kelas turunan untuk menimpa metode saat ini.
Menurut http://www.php.net/manual/en/language.oop5.static.php tidak ada $self. Hanya ada $this, untuk merujuk ke instance kelas saat ini (objek), dan diri, yang dapat digunakan untuk merujuk ke anggota statis kelas. Perbedaan antara instance objek dan kelas mulai berlaku di sini.
Saya percaya pertanyaannya bukan apakah Anda dapat memanggil anggota statis kelas dengan menelepon ClassName::staticMember. Pertanyaannya adalah apa perbedaan antara menggunakan self::classmemberdan $this->classmember.
Misalnya, kedua contoh berikut berfungsi tanpa kesalahan, baik Anda menggunakan self::atau$this->
Sangat lucu bahwa Anda memulai jawaban Anda dengan "Saya percaya pertanyaan itu bukan apakah Anda dapat memanggil anggota statis kelas dengan memanggil ClassName :: staticMember. Pertanyaannya adalah apa perbedaan antara menggunakan self :: classmember dan $ this-> classmember" dan kemudian Anda melanjutkan untuk tidak menunjukkan perbedaan sama sekali. Bahkan, Anda menunjukkan contoh tempat dua opsi bekerja secara identik. -1
Buttle Butkus
Meskipun demikian bermanfaat. Cakupannya tentang resolusi dan bagian ini tidak jelas dalam manual php. Saya masih merasakan
manfaatnya
2
Fatal error: Access to undeclared static property: Person::$name in D:\LAMP\www\test.php on line 16
K-Gun
16
self merujuk kelas saat ini (di mana ia disebut),
$thismerujuk objek saat ini. Anda dapat menggunakan statis alih-alih mandiri. Lihat contohnya:
Pointer objek $thisuntuk merujuk ke objek saat ini.
Nilai kelas staticmengacu pada objek saat ini.
Nilai kelas selfmerujuk ke kelas tepat yang didefinisikan dalam.
Nilai kelas parentmengacu pada induk dari kelas yang tepat itu didefinisikan dalam.
Lihat contoh berikut yang menunjukkan kelebihan beban.
<?php
class A {publicstaticfunction newStaticClass(){returnnewstatic;}publicstaticfunction newSelfClass(){returnnewself;}publicfunction newThisClass(){returnnew $this;}}class B extends A
{publicfunction newParentClass(){returnnew 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());// Aclass C extends B
{publicstaticfunction newSelfClass(){returnnewself;}}
$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"
Sebagian besar waktu Anda ingin merujuk ke kelas saat ini yang mengapa Anda menggunakan staticatau $this. Namun, ada kalanya Anda membutuhkannyaself karena Anda menginginkan kelas asli terlepas dari apa yang meluasnya. (Sangat, sangat jarang)
Itu adalah hasil untuk 2 000 000 berjalan, dan di sini adalah kode yang saya gunakan:
<?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 =newTleb\Benchmark\Benchmark(2000000);classFoo{publicfunction calling_this(){
$this->called();}publicfunction calling_self(){self::called();}publicfunction calling_static(){static::called();}publicstaticfunction called(){}}
$b->add('$this->',function(){ $foo =newFoo; $foo->calling_this();});
$b->add('self::',function(){ $foo =newFoo; $foo->calling_self();});
$b->add('static::',function(){ $foo =newFoo; $foo->calling_static();});
$b->run();
Memanggil fungsi no-op 2 000 000 kali berlangsung 1s. Harus mencintai PHP.
rr-
PHP tua yang bagus. :) Tapi panggilan = 0,001 ms. Apakah seburuk itu?
tleb
Saya percaya ini (dan hal-hal serupa) adalah mengapa hal-hal seperti ORM terasa lambat kecuali jika Anda melakukan cache, dan generator situs statis adalah sesuatu.
rr-
2
Secara teori seharusnya mengambil 1 siklus clock prosesor, yang membuat sekitar 1 / 2e9 s = 0.5 nshari-hari ini
Buddy
Baca kembali jawabanku. Hati-hati: itu menciptakan kelas juga. Saya tidak tahu mengapa saya tidak menggunakan usekata kunci tbh, tapi saya tidak punya PHP lagi untuk mengulang tolok ukur, dan saya tidak merasa ingin menginstalnya kembali.
tleb
13
Ketika selfdigunakan dengan ::operator itu merujuk ke kelas saat ini, yang dapat dilakukan baik dalam konteks statis dan non-statis. $thismengacu pada objek itu sendiri. Selain itu, sangat sah untuk digunakan $thisuntuk memanggil metode statis (tetapi tidak merujuk ke bidang).
Saya mengalami pertanyaan yang sama dan jawaban sederhana adalah:
$this membutuhkan turunan dari kelas
self:: tidak
Setiap kali Anda menggunakan metode statis atau atribut statis dan ingin memanggil mereka tanpa objek dari kelas Anda perlu menggunakan self:untuk memanggil mereka, karena $thisselalu membutuhkan objek yang akan dibuat.
$thismerujuk ke objek kelas saat ini, selfmengacu ke kelas saat ini (Bukan objek). Kelas adalah cetak biru objek. Jadi Anda mendefinisikan kelas, tetapi Anda membangun objek.
Jadi dengan kata lain, gunakan self for staticdan this for none-static members or methods.
juga dalam skenario anak / orang tua self / parentsebagian besar digunakan untuk mengidentifikasi anggota dan metode kelas anak dan orang tua.
Hanya untuk tujuan informasi, pada PHP 5.3 ketika berhadapan dengan objek instantiated untuk mendapatkan nilai lingkup saat ini, sebagai lawan dari penggunaan static::, seseorang dapat menggunakan $this::seperti itu.
classFoo{const NAME ='Foo';//Always Foo::NAME (Foo) due to selfprotectedstatic $staticName =self::NAME;publicfunction __construct(){
echo $this::NAME;}publicfunction getStaticName(){
echo $this::$staticName;}}classBarextendsFoo{const NAME ='FooBar';/**
* override getStaticName to output Bar::NAME
*/publicfunction getStaticName(){
$this::$staticName = $this::NAME;
parent::getStaticName();}}
$foo =newFoo;//outputs Foo
$bar =newBar;//outputs FooBar
$foo->getStaticName();//outputs Foo
$bar->getStaticName();//outputs FooBar
$foo->getStaticName();//outputs FooBar
Menggunakan kode di atas bukan praktik yang umum atau disarankan, tetapi hanya untuk menggambarkan penggunaannya, dan bertindak sebagai lebih dari "Tahukah Anda?" mengacu pada pertanyaan poster asli.
Ini juga mewakili penggunaan $object::CONSTANTmisalnya echo $foo::NAME;sebagai lawan$this::NAME;
Gunakan selfjika Anda ingin memanggil metode kelas tanpa membuat objek / instance kelas itu, sehingga menghemat RAM (kadang-kadang menggunakan diri untuk tujuan itu). Dengan kata lain, sebenarnya memanggil metode secara statis. Gunakan thisuntuk perspektif objek.
Menurut php.net ada tiga kata kunci khusus dalam konteks ini: self, parentdan static. Mereka digunakan untuk mengakses properti atau metode dari dalam definisi kelas.
$this, di sisi lain, digunakan untuk memanggil instance dan metode dari kelas apa saja selama kelas itu dapat diakses.
self :: kata kunci yang digunakan untuk kelas saat ini dan pada dasarnya digunakan untuk mengakses anggota statis, metode, dan konstanta. Tetapi dalam kasus $ this Anda tidak dapat memanggil anggota statis, metode dan fungsi.
Anda dapat menggunakan kata kunci self :: di kelas lain dan mengakses anggota statis, metode, dan konstanta. Ketika akan diperluas dari kelas induk dan sama dalam kasus $ kata kunci ini . Anda dapat mengakses anggota, metode, dan fungsi yang tidak statis di kelas lain ketika akan diperluas dari kelas induk.
Kode yang diberikan di bawah ini adalah contoh dari self :: dan $ this keyword. Cukup salin dan tempel kode dalam file kode Anda dan lihat hasilnya.
class cars{var $doors=4;static $car_wheel=4;publicfunction 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());
Jawaban:
Jawaban singkat
Jawaban Lengkap
Berikut adalah contoh penggunaan yang benar dari
$this
danself
untuk variabel anggota yang tidak statis dan statis:Berikut ini adalah contoh penggunaan salah
$this
danself
untuk variabel anggota tidak-statis dan statis:Berikut adalah contoh polimorfisme dengan
$this
untuk fungsi anggota:Berikut adalah contoh menekan perilaku polimorfik dengan menggunakan
self
untuk fungsi anggota:Dari http://www.phpbuilder.com/board/showthread.php?t=10354489 :
Oleh http://board.phpbuilder.com/member.php?145249-laserlight
sumber
self
digunakan dengan operator resolusi lingkup::
untuk merujuk ke kelas saat ini; ini dapat dilakukan dalam konteks statis dan non-statis. Selain itu, sangat sah untuk digunakan$this
untuk memanggil metode statis (tetapi tidak untuk bidang referensi).$this::
?Kata kunci sendiri TIDAK merujuk hanya ke 'kelas saat ini', setidaknya tidak dengan cara yang membatasi Anda untuk anggota statis. Dalam konteks anggota non-statis,
self
juga menyediakan cara untuk melewati vtable ( lihat wiki pada vtable ) untuk objek saat ini. Sama seperti yang dapat Anda gunakanparent::methodName()
untuk memanggil versi orang tua dari suatu fungsi, sehingga Anda dapat meneleponself::methodName()
untuk memanggil implementasi metode saat ini di kelas.Ini akan menampilkan:
sayHello()
menggunakan$this
pointer, sehingga vtable dipanggil untuk memanggilGeek::getTitle()
.sayGoodbye()
menggunakanself::getTitle()
, jadi vtable tidak digunakan, danPerson::getTitle()
dipanggil. Dalam kedua kasus, kita berhadapan dengan metode objek yang dipakai, dan memiliki akses ke$this
pointer dalam fungsi yang disebut.sumber
self
terletak" / "definisi kelas itu adalah bagian literal dari" serta "kelas objek" (yang sebenarnya akan menjadistatic
).$this::
?$this::
; semua kemungkinan kasus sudah dicakup oleh sintaksis yang lebih umum digunakan. Tergantung pada apa yang Anda maksud, penggunaan$this->
,self::
ataustatic::
.JANGAN GUNAKAN
self::
, gunakanstatic::
Ada aspek lain dari diri :: yang layak disebut. Mengganggu
self::
mengacu pada ruang lingkup pada titik definisi bukan pada titik eksekusi . Pertimbangkan kelas sederhana ini dengan dua metode:Jika kita memanggil
Person::status()
kita akan melihat "Orang itu hidup". Sekarang pertimbangkan apa yang terjadi ketika kita membuat kelas yang mewarisi dari ini:Memanggil
Deceased::status()
kita akan berharap untuk melihat "Orang sudah meninggal" namun apa yang kita lihat adalah "Orang itu hidup" karena ruang lingkup berisi definisi metode asli ketika panggilan keself::getStatus()
didefinisikan.PHP 5.3 punya solusinya. yang
static::
menerapkan Operator resolusi "terlambat statis mengikat" yang merupakan cara mewah untuk mengatakan bahwa itu terikat pada lingkup kelas yang disebut. Ubah barisstatus()
menjadistatic::getStatus()
dan hasilnya adalah apa yang Anda harapkan. Dalam versi PHP yang lebih lama, Anda harus menemukan kludge untuk melakukan ini.Lihat Dokumentasi PHP
Jadi untuk menjawab pertanyaan tidak seperti yang diminta ...
$this->
merujuk ke objek saat ini (turunan dari suatu kelas), sedangkanstatic::
merujuk ke suatu kelassumber
getStatus
metode sebagai metode yang saya sebut contoh kelas, bukan kelas.self::
, Anda bisa mendapatkan itu, kurang membingungkan, dengan menggunakan nama kelas tertentu, misMyClass::
.Untuk benar-benar memahami apa yang kita bicarakan ketika kita berbicara tentang
self
lawan$this
, kita harus benar-benar menggali apa yang terjadi pada tingkat konseptual dan praktis. Saya benar-benar tidak merasakan jawaban melakukan hal ini dengan tepat, jadi inilah usaha saya.Mari kita mulai dengan berbicara tentang apa kelas dan objek itu.
Kelas Dan Objek, Secara Konseptual
Jadi, apa adalah sebuah kelas ? Banyak orang mendefinisikannya sebagai cetak biru atau templat untuk suatu objek. Bahkan, Anda dapat membaca lebih lanjut Tentang Kelas Di PHP Di Sini . Dan sampai batas tertentu itulah sebenarnya. Mari kita lihat sebuah kelas:
Seperti yang Anda tahu, ada properti di kelas yang dipanggil
$name
dan metode (fungsi) dipanggilsayHello()
.Ini sangat penting untuk dicatat bahwa kelas adalah struktur statis. Yang berarti bahwa kelas
Person
, setelah didefinisikan, selalu sama di mana pun Anda melihatnya.Objek di sisi lain adalah apa yang disebut turunan Kelas. Artinya adalah bahwa kita mengambil "cetak biru" kelas, dan menggunakannya untuk membuat salinan yang dinamis. Salinan ini sekarang secara khusus terkait dengan variabel tempat penyimpanannya. Oleh karena itu, setiap perubahan pada instance adalah lokal untuk instance tersebut.
Kami membuat instance baru kelas menggunakan
new
operator.Oleh karena itu, kita katakan bahwa Kelas adalah struktur global, dan Obyek adalah struktur lokal. Jangan khawatir tentang
->
sintaks lucu itu , kita akan membahasnya sedikit lagi.Satu hal lain yang harus kita bicarakan, adalah bahwa kita dapat memeriksa apakah instance adalah
instanceof
kelas tertentu:$bob instanceof Person
yang mengembalikan boolean jika$bob
instance dibuat menggunakanPerson
kelas, atau anak dariPerson
.Mendefinisikan Negara
Jadi mari kita gali sedikit ke dalam apa yang sebenarnya mengandung kelas Ada 5 jenis "hal" yang dikandung kelas:
Properti - Pikirkan ini sebagai variabel yang akan berisi setiap instance.
Properti Statis - Pikirkan ini sebagai variabel yang dibagikan di tingkat kelas. Berarti mereka tidak pernah disalin oleh setiap contoh.
Metode - Ini adalah fungsi yang masing-masing instance akan berisi (dan beroperasi pada instance).
Metode Statis - Ini adalah fungsi yang dibagikan di seluruh kelas. Mereka tidak beroperasi pada instance, melainkan pada properti statis saja.
Konstanta - Konstanta yang diselesaikan kelas. Tidak masuk lebih dalam di sini, tetapi menambahkan untuk kelengkapan:
Jadi pada dasarnya, kami menyimpan informasi pada kelas dan objek kontainer menggunakan "petunjuk" tentang statis yang mengidentifikasi apakah informasi tersebut dibagikan (dan karenanya statis) atau tidak (dan karenanya dinamis).
Negara dan Metode
Di dalam suatu metode, instance objek diwakili oleh
$this
variabel. Keadaan saat objek itu ada di sana, dan bermutasi (mengubah) properti apa pun akan menghasilkan perubahan ke instance itu (tetapi tidak yang lain).Jika suatu metode disebut secara statis,
$this
variabel tidak didefinisikan . Ini karena tidak ada instance yang terkait dengan panggilan statis.Yang menarik di sini adalah bagaimana panggilan statis dibuat. Jadi mari kita bicara tentang bagaimana kita mengakses negara:
Mengakses negara
Jadi sekarang kita telah menyimpan status itu, kita perlu mengaksesnya. Ini bisa menjadi sedikit rumit (atau jauh lebih sedikit), jadi mari kita bagi menjadi dua sudut pandang: dari luar instance / kelas (katakanlah dari pemanggilan fungsi normal, atau dari lingkup global), dan di dalam instance / class (dari dalam metode pada objek).
Dari Luar Instance / Kelas
Dari luar instance / kelas, aturan kami cukup sederhana dan dapat diprediksi. Kami memiliki dua operator, dan masing-masing memberi tahu kami segera jika kami berurusan dengan instance atau static kelas:
->
- object-operator - Ini selalu digunakan ketika kita mengakses instance.Penting untuk dicatat bahwa panggilan
Person->foo
tidak masuk akal (karenaPerson
kelas, bukan instance). Oleh karena itu, itu adalah kesalahan parse.::
- scope-resolution-operator - Ini selalu digunakan untuk mengakses properti atau metode statis Class.Selain itu, kita dapat memanggil metode statis pada objek dengan cara yang sama:
Ini sangat penting untuk dicatat bahwa ketika kita melakukan ini dari luar , misalnya objek tersembunyi dari
bar()
metode. Artinya sama persis dengan menjalankan:Karena itu,
$this
tidak didefinisikan dalam panggilan statis.Dari Inside Of An Instance / Class
Banyak hal berubah di sini. Operator yang sama digunakan, tetapi artinya menjadi kabur secara signifikan.
Operator objek
->
masih digunakan untuk melakukan panggilan ke keadaan instance objek.Memanggil
bar()
metode pada$foo
(turunan dariFoo
) menggunakan objek-operator:$foo->bar()
akan menghasilkan versi turunan dari$a
.Jadi itulah yang kami harapkan.
Arti
::
operator meskipun berubah. Itu tergantung pada konteks panggilan ke fungsi saat ini:Dalam konteks statis
Dalam konteks statis, semua panggilan yang dibuat
::
juga akan statis. Mari kita lihat sebuah contoh:Memanggil
Foo::bar()
akan memanggilbaz()
metode statis, dan karenanya$this
akan tidak diisi. Perlu dicatat bahwa dalam versi PHP terbaru (5.3+) ini akan memicuE_STRICT
kesalahan, karena kami memanggil metode non-statis secara statis.Dalam konteks instance
Di dalam konteks instance di sisi lain, panggilan yang dibuat menggunakan
::
tergantung pada penerima panggilan (metode yang kami panggil). Jika metode ini didefinisikanstatic
, maka akan menggunakan panggilan statis. Jika tidak, itu akan meneruskan informasi instan.Jadi, melihat kode di atas, panggilan
$foo->bar()
akan kembalitrue
, karena panggilan "statis" terjadi di dalam konteks instance.Masuk akal? Tidak mengira begitu. Ini membingungkan.
Kata kunci pintas
Karena mengikat semuanya bersama-sama menggunakan nama kelas agak kotor, PHP menyediakan 3 kata kunci "jalan pintas" dasar untuk mempermudah penyelesaian ruang lingkup.
self
- Ini merujuk pada nama kelas saat ini. Jadiself::baz()
sama denganFoo::baz()
di dalamFoo
kelas (metode apa pun di atasnya).parent
- Ini merujuk pada induk dari kelas saat ini.static
- Ini mengacu pada kelas yang dipanggil. Berkat warisan, kelas anak dapat menimpa metode dan properti statis. Jadi memanggil mereka menggunakanstatic
bukan nama kelas memungkinkan kita untuk menyelesaikan dari mana panggilan itu berasal, daripada tingkat saat ini.Contohnya
Cara termudah untuk memahami ini adalah mulai melihat beberapa contoh. Mari pilih kelas:
Sekarang, kami juga melihat warisan di sini. Abaikan sejenak bahwa ini adalah model objek yang buruk, tetapi mari kita lihat apa yang terjadi ketika kita bermain dengan ini:
Jadi penghitung ID dibagikan di seluruh instance dan anak-anak (karena kami menggunakan
self
untuk mengaksesnya. Jika kami menggunakannyastatic
, kami bisa menimpanya dalam kelas anak).Perhatikan bahwa kami menjalankan metode
Person::getName()
instance setiap waktu. Tapi kami menggunakanparent::getName()
untuk melakukannya di salah satu kasus (kasus anak). Inilah yang membuat pendekatan ini kuat.Perhatian # 1
Perhatikan bahwa konteks panggilan adalah yang menentukan apakah instance digunakan. Karena itu:
Tidak selalu benar.
Sekarang benar - benar aneh di sini. Kami memanggil kelas yang berbeda, tetapi
$this
yang diteruskan keFoo::isFoo()
metode adalah turunan dari$bar
.Ini dapat menyebabkan semua jenis bug dan WTF-ery konseptual. Jadi saya akan sangat menyarankan menghindari
::
operator dari dalam metode instan pada apa pun kecuali yang tiga virtual "short-cut" kata kunci (static
,self
, danparent
).Perhatian # 2
Perhatikan bahwa metode dan properti statis dibagikan oleh semua orang. Itu membuat mereka pada dasarnya variabel global. Dengan semua masalah yang sama dengan global. Jadi saya akan benar-benar ragu untuk menyimpan informasi dalam metode / properti statis kecuali Anda merasa nyaman dengan itu menjadi benar-benar global.
Perhatian # 3
Secara umum, Anda ingin menggunakan apa yang dikenal sebagai Late-Static-Binding dengan menggunakan
static
alih-alihself
. Tetapi perhatikan bahwa mereka bukan hal yang sama, jadi mengatakan "selalu gunakanstatic
bukannyaself
benar-benar picik. Sebaliknya, berhenti dan pikirkan tentang panggilan yang ingin Anda buat dan pikirkan jika Anda ingin kelas anak-anak dapat menimpa statis yang diselesaikan panggilan.TL / DR
Sayang sekali, kembali dan baca. Mungkin terlalu lama, tapi itu lama karena ini adalah topik yang kompleks
TL / DR # 2
Baiklah. Singkatnya,
self
digunakan untuk mereferensikan nama kelas saat ini di dalam kelas, di mana$this
merujuk pada instance objek saat ini . Perhatikan bahwa ituself
adalah jalan pintas salin / tempel. Anda dapat dengan aman menggantinya dengan nama kelas Anda, dan itu akan berfungsi dengan baik. Tetapi$this
adalah variabel dinamis yang tidak dapat ditentukan sebelumnya (dan mungkin bahkan bukan kelas Anda).TL / DR # 3
Jika objek-operator digunakan (
->
), maka Anda selalu tahu Anda berurusan dengan sebuah instance. Jika lingkup-resolusi-operator digunakan (::
), Anda memerlukan informasi lebih lanjut tentang konteksnya (apakah kita sudah berada dalam konteks objek? Apakah kita berada di luar objek? Dll).sumber
$this
tidak akan ditentukan jika Anda mengikuti "Standar Ketat" dan jangan panggil metode statis yang tidak didefinisikan sebagai statis. Saya melihat hasil yang Anda jelaskan di sini: 3v4l.org/WeHVM Setuju, sangat aneh.Foo::isFoo()
disebut statis,$this
tidak akan didefinisikan. Itu perilaku yang lebih intuitif menurut saya. - Hasil lain yang berbeda diberikan jikaBar
diperpanjang dariFoo
. Maka panggilanFoo::isFoo()
akan benar-benar berada dalam konteks instance (tidak spesifik untuk PHP7).self
(bukan $ self) mengacu pada jenis kelas, di mana seperti$this
merujuk pada instance kelas saat ini.self
digunakan untuk fungsi anggota statis untuk memungkinkan Anda mengakses variabel anggota statis.$this
digunakan dalam fungsi anggota yang tidak statis, dan merupakan referensi ke instance dari kelas di mana fungsi anggota dipanggil.Karena
this
adalah sebuah objek, Anda menggunakannya seperti:$this->member
Karena
self
bukan objek, itu pada dasarnya adalah tipe yang secara otomatis merujuk ke kelas saat ini, Anda menggunakannya seperti:self::member
sumber
$this->
digunakan untuk merujuk pada instance spesifik dari variabel kelas (variabel anggota) atau metode.$ derek sekarang adalah contoh spesifik dari Person. Setiap Orang memiliki nama depan dan nama belakang, tetapi $ derek memiliki nama depan dan nama belakang tertentu (Derek Martin). Di dalam instance $ derek, kita dapat merujuknya sebagai $ this-> first_name dan $ this-> last_name
ClassName :: digunakan untuk merujuk pada tipe kelas itu, dan variabel statisnya, metode statis. Jika ini membantu, Anda dapat secara mental mengganti kata "statis" dengan "dibagikan". Karena dibagikan, mereka tidak dapat merujuk ke $ this, yang merujuk pada contoh spesifik (tidak dibagikan). Variabel Statis (mis. $ Db_connection statis) dapat dibagi di antara semua instance dari jenis objek. Sebagai contoh, semua objek database berbagi satu koneksi (koneksi $ statis).
Variabel Statis Contoh: Berpura-pura kita memiliki kelas basis data dengan variabel anggota tunggal: static $ num_connections; Sekarang, letakkan ini di konstruktor:
Sama seperti objek memiliki konstruktor, mereka juga memiliki destruktor, yang dieksekusi ketika objek mati atau tidak disetel:
Setiap kali kita membuat instance baru, penghitung koneksi kita akan bertambah satu. Setiap kali kita menghancurkan atau berhenti menggunakan instance, itu akan mengurangi penghitung koneksi satu per satu. Dengan cara ini, kita dapat memonitor jumlah instance dari objek database yang telah kita gunakan dengan:
Karena $ num_connections bersifat statis (dibagi-pakai), ia akan mencerminkan jumlah total objek database aktif. Anda mungkin telah melihat teknik ini digunakan untuk berbagi koneksi database di antara semua instance dari kelas database. Ini dilakukan karena membuat koneksi database membutuhkan waktu lama, jadi yang terbaik untuk membuatnya hanya satu, dan membaginya (ini disebut Pola Singleton).
Metode Statis (yaitu public static View :: format_phone_number ($ digit)) dapat digunakan TANPA pertama-tama instantiating salah satu objek tersebut (yaitu Mereka tidak merujuk secara internal ke $ this).
Contoh Metode Statis:
Seperti yang Anda lihat, fungsi statis publik prettyName tidak tahu apa-apa tentang objek. Ini hanya bekerja dengan parameter yang Anda lewati, seperti fungsi normal yang bukan bagian dari objek. Lalu, mengapa repot-repot, kalau saja kita tidak memilikinya sebagai bagian dari objek?
DIRI :: Jika Anda melakukan pengkodean di luar objek yang memiliki metode statis yang ingin Anda rujuk, Anda harus memanggilnya menggunakan nama objek View :: format_phone_number ($ phone_number); Jika Anda mengkode di dalam objek yang memiliki metode statis yang ingin Anda lihat, Anda bisa melakukannya menggunakan objek nama View :: format_phone_number ($ pn), ATAU Anda dapat menggunakan self :: format_phone_number ($ pn) shortcut
Hal yang sama berlaku untuk variabel statis: Contoh: Lihat :: templates_path versus self :: templates_path
Di dalam kelas DB, jika kita merujuk pada metode statis dari beberapa objek lain, kita akan menggunakan nama objek: Contoh: Session :: getUsersOnline ();
Tetapi jika kelas DB ingin merujuk ke variabel statisnya sendiri, ia hanya akan mengatakan sendiri: Contoh: self :: connection;
Semoga itu membantu menjernihkan semuanya :)
sumber
$
tanda. Misalnyaself::$templates_path
Dari posting blog ini :
sumber
Di PHP, Anda menggunakan kata kunci mandiri untuk mengakses properti dan metode statis.
Masalahnya adalah Anda dapat mengganti
$this->method()
denganself::method()
mana saja, terlepas dari apakahmethod()
dinyatakan statis atau tidak. Jadi yang mana yang harus Anda gunakan?Pertimbangkan kode ini:
Dalam contoh ini,
self::who()
akan selalu menampilkan 'induk', sementara$this->who()
akan bergantung pada kelas apa yang dimiliki objek.Sekarang kita dapat melihat bahwa diri merujuk ke kelas yang disebutnya, sementara
$this
mengacu pada kelas objek saat ini .Jadi, Anda harus menggunakan diri sendiri saat
$this
tidak tersedia, atau ketika Anda tidak ingin mengizinkan kelas turunan untuk menimpa metode saat ini.sumber
Di dalam definisi kelas,
$this
mengacu pada objek saat ini, sementaraself
mengacu pada kelas saat ini.Kita perlu merujuk ke elemen kelas menggunakan
self
, dan merujuk ke elemen objek menggunakan$this
.sumber
sumber
Menurut http://www.php.net/manual/en/language.oop5.static.php tidak ada
$self
. Hanya ada$this
, untuk merujuk ke instance kelas saat ini (objek), dan diri, yang dapat digunakan untuk merujuk ke anggota statis kelas. Perbedaan antara instance objek dan kelas mulai berlaku di sini.sumber
Saya percaya pertanyaannya bukan apakah Anda dapat memanggil anggota statis kelas dengan menelepon
ClassName::staticMember
. Pertanyaannya adalah apa perbedaan antara menggunakanself::classmember
dan$this->classmember
.Misalnya, kedua contoh berikut berfungsi tanpa kesalahan, baik Anda menggunakan
self::
atau$this->
sumber
Fatal error: Access to undeclared static property: Person::$name in D:\LAMP\www\test.php on line 16
self
merujuk kelas saat ini (di mana ia disebut),$this
merujuk objek saat ini. Anda dapat menggunakan statis alih-alih mandiri. Lihat contohnya:Keluaran: orangtua anak
sumber
$this
untuk merujuk ke objek saat ini.static
mengacu pada objek saat ini.self
merujuk ke kelas tepat yang didefinisikan dalam.parent
mengacu pada induk dari kelas yang tepat itu didefinisikan dalam.Lihat contoh berikut yang menunjukkan kelebihan beban.
Sebagian besar waktu Anda ingin merujuk ke kelas saat ini yang mengapa Anda menggunakan
static
atau$this
. Namun, ada kalanya Anda membutuhkannyaself
karena Anda menginginkan kelas asli terlepas dari apa yang meluasnya. (Sangat, sangat jarang)sumber
Karena tidak seorang pun di sini berbicara tentang pertunjukan, berikut ini adalah tolok ukur kecil yang saya lakukan (5.6):
Itu adalah hasil untuk 2 000 000 berjalan, dan di sini adalah kode yang saya gunakan:
sumber
1 / 2e9 s = 0.5 ns
hari-hari iniuse
kata kunci tbh, tapi saya tidak punya PHP lagi untuk mengulang tolok ukur, dan saya tidak merasa ingin menginstalnya kembali.Ketika
self
digunakan dengan::
operator itu merujuk ke kelas saat ini, yang dapat dilakukan baik dalam konteks statis dan non-statis.$this
mengacu pada objek itu sendiri. Selain itu, sangat sah untuk digunakan$this
untuk memanggil metode statis (tetapi tidak merujuk ke bidang).sumber
Saya mengalami pertanyaan yang sama dan jawaban sederhana adalah:
$this
membutuhkan turunan dari kelasself::
tidakSetiap kali Anda menggunakan metode statis atau atribut statis dan ingin memanggil mereka tanpa objek dari kelas Anda perlu menggunakan
self:
untuk memanggil mereka, karena$this
selalu membutuhkan objek yang akan dibuat.sumber
$this
merujuk ke objek kelas saat ini,self
mengacu ke kelas saat ini (Bukan objek). Kelas adalah cetak biru objek. Jadi Anda mendefinisikan kelas, tetapi Anda membangun objek.Jadi dengan kata lain, gunakan
self for static
danthis for none-static members or methods
.juga dalam skenario anak / orang tua
self / parent
sebagian besar digunakan untuk mengidentifikasi anggota dan metode kelas anak dan orang tua.sumber
Selain itu karena
$this::
belum dibahas.Hanya untuk tujuan informasi, pada PHP 5.3 ketika berhadapan dengan objek instantiated untuk mendapatkan nilai lingkup saat ini, sebagai lawan dari penggunaan
static::
, seseorang dapat menggunakan$this::
seperti itu.http://ideone.com/7etRHy
Menggunakan kode di atas bukan praktik yang umum atau disarankan, tetapi hanya untuk menggambarkan penggunaannya, dan bertindak sebagai lebih dari "Tahukah Anda?" mengacu pada pertanyaan poster asli.
Ini juga mewakili penggunaan
$object::CONSTANT
misalnyaecho $foo::NAME;
sebagai lawan$this::NAME;
sumber
Gunakan
self
jika Anda ingin memanggil metode kelas tanpa membuat objek / instance kelas itu, sehingga menghemat RAM (kadang-kadang menggunakan diri untuk tujuan itu). Dengan kata lain, sebenarnya memanggil metode secara statis. Gunakanthis
untuk perspektif objek.sumber
Kasus 1: Penggunaan
self
dapat digunakan untuk konstanta kelasJika Anda ingin menyebutnya di luar kelas, gunakan
classA::POUNDS_TO_KILOGRAMS
untuk mengakses konstantaKasus 2: Untuk properti statis
sumber
Menurut php.net ada tiga kata kunci khusus dalam konteks ini:
self
,parent
danstatic
. Mereka digunakan untuk mengakses properti atau metode dari dalam definisi kelas.$this
, di sisi lain, digunakan untuk memanggil instance dan metode dari kelas apa saja selama kelas itu dapat diakses.sumber
self :: kata kunci yang digunakan untuk kelas saat ini dan pada dasarnya digunakan untuk mengakses anggota statis, metode, dan konstanta. Tetapi dalam kasus $ this Anda tidak dapat memanggil anggota statis, metode dan fungsi.
Anda dapat menggunakan kata kunci self :: di kelas lain dan mengakses anggota statis, metode, dan konstanta. Ketika akan diperluas dari kelas induk dan sama dalam kasus $ kata kunci ini . Anda dapat mengakses anggota, metode, dan fungsi yang tidak statis di kelas lain ketika akan diperluas dari kelas induk.
Kode yang diberikan di bawah ini adalah contoh dari self :: dan $ this keyword. Cukup salin dan tempel kode dalam file kode Anda dan lihat hasilnya.
sumber