Di PHP 5, apa perbedaan antara menggunakan self
dan $this
?
Kapan masing-masing sesuai?
Di PHP 5, apa perbedaan antara menggunakan self
dan $this
?
Kapan masing-masing sesuai?
Jawaban:
Gunakan
$this
untuk merujuk ke objek saat ini. Gunakanself
untuk merujuk ke kelas saat ini. Dengan kata lain, gunakan$this->member
untuk anggota non-statis, gunakanself::$member
untuk anggota statis.
Berikut adalah contoh penggunaan yang benar dari $this
dan self
untuk variabel anggota yang tidak statis dan statis:
<?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();
?>
Berikut ini adalah contoh penggunaan salah$this
dan self
untuk variabel anggota tidak-statis dan statis:
<?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();
?>
Berikut adalah contoh polimorfisme dengan $this
untuk 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 self
untuk 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()
memanggilfoo()
fungsi anggota dari apa pun jenis yang tepat dari objek saat ini. Jika objeknya adalahtype X
, ia memanggilX::foo()
. Jika objeknya adalahtype Y
, ia memanggilY::foo()
. Tetapi dengan self :: foo (),X::foo()
selalu dipanggil.
Dari http://www.phpbuilder.com/board/showthread.php?t=10354489 :
Oleh http://board.phpbuilder.com/member.php?145249-laserlight
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 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.
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();
Ini akan menampilkan:
Halo, saya Ludwig si pecandu
Selamat tinggal dari Ludwig, orang itu
sayHello()
menggunakan $this
pointer, 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 $this
pointer dalam fungsi yang disebut.
self
terletak" / "definisi kelas itu adalah bagian literal dari" serta "kelas objek" (yang sebenarnya akan menjadi static
).
$this::
?
$this::
; semua kemungkinan kasus sudah dicakup oleh sintaksis yang lebih umum digunakan. Tergantung pada apa yang Anda maksud, penggunaan $this->
, self::
atau static::
.
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:
class Person
{
public static function status()
{
self::getStatus();
}
protected static function 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:
class Deceased extends Person
{
protected static function 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.
Lihat Dokumentasi PHP
Jadi untuk menjawab pertanyaan tidak seperti yang diminta ...
$this->
merujuk ke objek saat ini (turunan dari suatu kelas), sedangkan static::
merujuk ke suatu kelas
getStatus
metode sebagai metode yang saya sebut contoh kelas, bukan kelas.
self::
, Anda bisa mendapatkan itu, kurang membingungkan, dengan menggunakan nama kelas tertentu, mis MyClass::
.
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.
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:
class Person {
public $name = 'my name';
public function sayHello() {
echo "Hello";
}
}
Seperti yang Anda tahu, ada properti di kelas yang dipanggil $name
dan 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 = new Person;
$adam = new Person;
$bob->name = 'Bob';
echo $adam->name; // "my name"
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 menggunakan Person
kelas, atau anak dari Person
.
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.
class Foo {
public $bar = 1;
}
Properti Statis - Pikirkan ini sebagai variabel yang dibagikan di tingkat kelas. Berarti mereka tidak pernah disalin oleh setiap contoh.
class Foo {
public static $bar = 1;
}
Metode - Ini adalah fungsi yang masing-masing instance akan berisi (dan beroperasi pada instance).
class Foo {
public function bar() {}
}
Metode Statis - Ini adalah fungsi yang dibagikan di seluruh kelas. Mereka tidak beroperasi pada instance, melainkan pada properti statis saja.
class Foo {
public static function bar() {}
}
Konstanta - Konstanta yang diselesaikan kelas. Tidak masuk lebih dalam di sini, tetapi menambahkan untuk kelengkapan:
class Foo {
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).
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:
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, 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 = new Person;
echo $bob->name;
Penting untuk dicatat bahwa panggilan Person->foo
tidak masuk akal (karena Person
kelas, 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, $this
tidak didefinisikan dalam panggilan statis.
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.
class Foo {
public $a = 1;
public function bar() {
return $this->a;
}
}
Memanggil bar()
metode pada $foo
(turunan dari Foo
) 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:
class Foo {
public function bar() {
return Foo::baz();
}
public function baz() {
return isset($this);
}
}
Memanggil Foo::bar()
akan memanggil baz()
metode statis, dan karenanya $this
akan tidak diisi. Perlu dicatat bahwa dalam versi PHP terbaru (5.3+) ini akan memicu E_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 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.
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 Foo
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 menggunakan static
bukan nama kelas memungkinkan kita untuk menyelesaikan dari mana panggilan itu berasal, daripada tingkat saat ini.
Cara termudah untuk memahami ini adalah mulai melihat beberapa contoh. Mari pilih kelas:
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();
}
}
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:
$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
Jadi penghitung ID dibagikan di seluruh instance dan anak-anak (karena kami menggunakan self
untuk 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.
Perhatikan bahwa konteks panggilan adalah yang menentukan apakah instance digunakan. Karena itu:
class Foo {
public function isFoo() {
return $this instanceof Foo;
}
}
Tidak selalu benar.
class Bar {
public function doSomething() {
return Foo::isFoo();
}
}
$b = new Bar;
var_dump($b->doSomething()); // bool(false)
Sekarang benar - benar aneh di sini. Kami memanggil kelas yang berbeda, tetapi $this
yang 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
).
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.
Secara umum, Anda ingin menggunakan apa yang dikenal sebagai Late-Static-Binding dengan menggunakan static
alih-alih self
. Tetapi perhatikan bahwa mereka bukan hal yang sama, jadi mengatakan "selalu gunakan static
bukannya self
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.
Sayang sekali, kembali dan baca. Mungkin terlalu lama, tapi itu lama karena ini adalah topik yang kompleks
Baiklah. Singkatnya, self
digunakan untuk mereferensikan nama kelas saat ini di dalam kelas, di mana $this
merujuk pada instance objek saat ini . Perhatikan bahwa itu self
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).
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).
$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 jika Bar
diperpanjang dari Foo
. Maka panggilan Foo::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
$this->
digunakan untuk merujuk pada instance spesifik dari variabel kelas (variabel anggota) atau metode.
Example:
$derek = new Person();
$ 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).
Contoh Metode Statis:
public static function prettyName($first_name, $last_name)
{
echo ucfirst($first_name).' '.ucfirst($last_name);
}
echo Person::prettyName($derek->first_name, $derek->last_name);
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 :)
$
tanda. Misalnyaself::$templates_path
Dari posting blog ini :
self
merujuk ke kelas saat iniself
dapat digunakan untuk memanggil fungsi statis dan referensi variabel anggota statisself
dapat digunakan di dalam fungsi statisself
juga dapat mematikan perilaku polimorfik dengan memintas vtable$this
mengacu pada objek saat ini$this
dapat digunakan untuk memanggil fungsi statis$this
tidak boleh digunakan untuk memanggil variabel anggota statis. Gunakanself
sebagai gantinya.$this
tidak dapat digunakan di dalam fungsi statis
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:
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();
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.
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
.
self::STAT // refer to a constant value
self::$stat // static variable
$this->stat // refer to an object variable
Berikut adalah contoh penggunaan $ this yang benar dan mandiri untuk variabel anggota yang tidak statis dan statis:
<?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();
?>
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::classmember
dan $this->classmember
.
Misalnya, kedua contoh berikut berfungsi tanpa kesalahan, baik Anda menggunakan self::
atau$this->
class Person{
private $name;
private $address;
public function __construct($new_name,$new_address){
$this->name = $new_name;
$this->address = $new_address;
}
}
class Person{
private $name;
private $address;
public function __construct($new_name,$new_address){
self::$name = $new_name;
self::$address = $new_address;
}
}
Fatal error: Access to undeclared static property: Person::$name in D:\LAMP\www\test.php on line 16
self
merujuk kelas saat ini (di mana ia disebut),
$this
merujuk objek saat ini. Anda dapat menggunakan statis alih-alih mandiri. Lihat contohnya:
class ParentClass {
function test() {
self::which(); // output 'parent'
$this->which(); // output 'child'
}
function which() {
echo 'parent';
}
}
class ChildClass extends ParentClass {
function which() {
echo 'child';
}
}
$obj = new ChildClass();
$obj->test();
Keluaran: orangtua anak
$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.
<?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"
Sebagian besar waktu Anda ingin merujuk ke kelas saat ini yang mengapa Anda menggunakan static
atau $this
. Namun, ada kalanya Anda membutuhkannya self
karena Anda menginginkan kelas asli terlepas dari apa yang meluasnya. (Sangat, sangat jarang)
Karena tidak seorang pun di sini berbicara tentang pertunjukan, berikut ini adalah tolok ukur kecil yang saya lakukan (5.6):
Name | Time | Percent
----------|---------|---------
$this-> | 0.99163 | 106.23%
self:: | 0.96912 | 103.82%
static:: | 0.93348 | 100%
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 = new Tleb\Benchmark\Benchmark(2000000);
class Foo
{
public function calling_this()
{
$this->called();
}
public function calling_self()
{
self::called();
}
public function calling_static()
{
static::called();
}
public static function called()
{
}
}
$b->add('$this->', function () { $foo = new Foo; $foo->calling_this(); });
$b->add('self::', function () { $foo = new Foo; $foo->calling_self(); });
$b->add('static::', function () { $foo = new Foo; $foo->calling_static(); });
$b->run();
1 / 2e9 s = 0.5 ns
hari-hari ini
use
kata kunci tbh, tapi saya tidak punya PHP lagi untuk mengulang tolok ukur, dan saya tidak merasa ingin menginstalnya kembali.
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.
$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
dan this 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.
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.
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
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
misalnya echo $foo::NAME;
sebagai lawan$this::NAME;
Kasus 1: Penggunaan self
dapat digunakan untuk konstanta kelas
class classA { const FIXED_NUMBER = 4; self :: POUNDS_TO_KILOGRAMS }
Jika Anda ingin menyebutnya di luar kelas, gunakan classA::POUNDS_TO_KILOGRAMS
untuk mengakses konstanta
Kasus 2: Untuk properti statis
class classC { fungsi publik __construct () { self :: $ _ counter ++; $ this-> num = self :: $ _ counter; } }
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;
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());