it-swarm.asia

Kapan harus menggunakan lebih dari $ ini?

Dalam PHP 5, apa perbedaan antara menggunakan self dan $this?

Kapan masing-masing sesuai?

1883
Casey Watson

Jawaban singkat

Gunakan $this untuk merujuk ke objek saat ini. Gunakan self untuk merujuk ke kelas saat ini. Dengan kata lain, gunakan $this->member untuk anggota yang tidak statis, gunakan self::$member untuk anggota statis.

Jawaban Lengkap

Berikut adalah contoh dari benar penggunaan $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();
?>

Ini adalah contoh dari salah penggunaan $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 self::$non_static_member . ' '
           . $this->static_member;
    }
}

new X();
?>

Berikut adalah contoh dari 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 ini adalah contoh dari 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 bahwa $this->foo() memanggil fungsi anggota foo() dari apa pun jenis persis 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.

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

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

1613
John Millikin

Kata kunci sendiri tidakTIDAKmerujuk 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 Anda dapat menggunakan parent::methodName() untuk memanggil versi fungsi orang tua, jadi Anda dapat memanggil 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 geek
Selamat tinggal dari Ludwig, orang itu

sayHello() menggunakan pointer $this, sehingga vtable dipanggil untuk memanggil Geek::getTitle(). sayGoodbye() menggunakan self::getTitle(), sehingga vtable tidak digunakan, dan Person::getTitle() dipanggil. Dalam kedua kasus, kita berurusan dengan metode objek yang dipakai, dan memiliki akses ke pointer $this dalam fungsi yang disebut.

726
nbeagle

JANGAN GUNAKAN self::, gunakan static::

Ada aspek lain dari diri :: yang layak disebut. Menggangguself:: mengacu pada ruang lingkup pada titik definisi bukan pada titik pelaksanaan . 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 telah meninggal" namun apa yang kita lihat adalah "Orang masih hidup" karena ruang lingkup berisi definisi metode asli ketika panggilan ke self::getStatus() telah didefinisikan.

PHP 5.3 punya solusinya. operatorstatic::resolution mengimplementasikan "late static binding" yang merupakan cara yang bagus untuk mengatakan bahwa ia terikat dengan ruang lingkup kelas yang disebut. Ubah baris di 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 PHP Dokumentasi

Jadi untuk menjawab pertanyaan tidak seperti yang diminta ...

$this-> merujuk ke objek saat ini (turunan dari sebuah kelas), sedangkan static:: merujuk ke sebuah kelas

441
Sqoo

self (bukan $ self) merujuk ke kelas type , sedangkan $this merujuk ke kelas instance saat ini. self untuk digunakan dalam fungsi anggota statis untuk memungkinkan Anda mengakses variabel anggota statis. $this digunakan dalam fungsi anggota yang tidak statis, dan merupakan referensi ke instance kelas tempat 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

115
MrZebra

$this-> digunakan untuk merujuk pada instance spesifik variabel kelas (variabel anggota) atau metode.

Example: 
$derek = new Person();

$ derek sekarang adalah contoh spesifik Person. Setiap Orang memiliki nama depan dan nama belakang, tetapi $ derek memiliki nama depan dan nama belakang yang spesifik (Derek Martin). Di dalam instance $ derek, kita bisa merujuk ke $ this-> first_name dan $ this-> last_name

ClassName :: digunakan untuk merujuk pada jenis 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. Static $ db_connection) 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 basis data aktif. Anda mungkin telah melihat teknik ini digunakan untuk berbagi koneksi database di antara semua instance dari kelas database. Ini dilakukan karena membuat koneksi basis data membutuhkan waktu lama, jadi yang terbaik untuk membuatnya hanya satu, dan membaginya (ini disebut Pola Singleton).

Metode Statis (mis. Tampilan statis publik :: format_phone_number ($ digit)) dapat digunakan TANPA pertama-tama instantiate salah satu objek tersebut (mis. 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?

  1. Pertama, melampirkan fungsi ke objek membantu Anda mengatur berbagai hal, sehingga Anda tahu di mana menemukannya.
  2. Kedua, ini mencegah konflik penamaan. Dalam proyek besar, Anda cenderung memiliki dua pengembang membuat fungsi getName (). Jika seseorang membuat ClassName1 :: getName (), dan yang lain membuat ClassName2 :: getName (), tidak ada masalah sama sekali. Tidak ada konflik. Yay metode statis!

SELF :: 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 mengkodekan inside objek yang memiliki metode statis yang ingin Anda rujuk, Anda dapat baik menggunakan nama objek Lihat :: format_phone_number ($ pn), OR Anda dapat menggunakan pintasan self :: format_phone_number ($ pn)

Hal yang sama berlaku untuk variabel statis: Contoh: View :: 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 self: Contoh: self :: connection;

Harapan yang membantu menjernihkan semuanya :)

96
lo_fye

Dari posting blog ini :

  • self mengacu pada kelas saat ini
  • self dapat digunakan untuk memanggil fungsi statis dan referensi variabel anggota statis
  • self dapat digunakan di dalam fungsi statis
  • self 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. Gunakan self sebagai gantinya.
  • $this tidak dapat digunakan di dalam fungsi statis
29
okconfused

Di PHP, Anda menggunakan kata kunci mandiri untuk mengakses properti dan metode statis.

Masalahnya adalah Anda dapat mengganti $this->method() dengan self::method()anywhere, 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 'parent', sedangkan $this->who() akan tergantung pada kelas apa yang dimiliki objek.

Sekarang kita dapat melihat bahwa self merujuk ke kelas yang dipanggil, sementara $this merujuk ke class dari objek saat ini .

Jadi, Anda harus menggunakan sendiri hanya ketika $this tidak tersedia, atau ketika Anda tidak ingin mengizinkan kelas turunan untuk menimpa metode saat ini.

25
ramin rostami

Di dalam definisi kelas, $ this merujuk ke objek saat ini, sementara self merujuk ke 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  
21
Tarun Singhal

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

Menurut http://www.php.net/manual/en/language.oop5.static.php tidak ada $self. Hanya ada $this, untuk merujuk pada instance kelas saat ini (objek), dan diri, yang dapat digunakan untuk merujuk pada anggota statis suatu kelas. Perbedaan antara instance objek dan kelas mulai berlaku di sini.

20
cruizer

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

15
Kabir Hossain

Saya yakin pertanyaannya bukan apakah Anda dapat memanggil anggota statis kelas dengan memanggil ClassName::staticMember. Pertanyaannya adalah apa perbedaan antara menggunakan self::classmember dan $this->classmember.

Misalnya, kedua contoh berikut berfungsi tanpa kesalahan, apakah 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;
    }
}
14
dr evil

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%

Itulah 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();
14
tleb
  • Pointer objek $ this untuk merujuk ke objek saat ini.
  • Nilai kelas "statis" mengacu pada objek saat ini.
  • Nilai kelas "diri" merujuk ke kelas yang tepat di mana ia didefinisikan.
  • Nilai kelas "induk" mengacu pada induk dari kelas yang tepat di mana ia didefinisikan.

Lihat contoh berikut yang menunjukkan kelebihan muatan.

<?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 perlu self karena Anda menginginkan kelas asli terlepas dari apa yang diperluas. (Sangat, sangat jarang)

14
Xeoncross

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 menggunakan $this untuk memanggil metode statis (tetapi tidak merujuk ke bidang).

13
mrDjouk

$this merujuk ke objek kelas saat ini, self merujuk 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.

7
Rakesh Singh

Selain itu karena $this:: belum dibahas.

Hanya untuk tujuan informasi, pada PHP 5.3 ketika berhadapan dengan objek instantiated untuk mendapatkan nilai ruang lingkup saat ini, dibandingkan dengan menggunakan static::, seseorang dapat menggunakan $this:: secara bergantian seperti itu.

http://ideone.com/7etRHy

class Foo
{
    const NAME = 'Foo';

    //Always Foo::NAME (Foo) due to self
    protected static $staticName = self::NAME;

    public function __construct()
    {
        echo $this::NAME;
    }

    public function getStaticName()
    {
       echo $this::$staticName;
    }
}

class Bar extends Foo
{
    const NAME = 'FooBar';

    /**
     * override getStaticName to output Bar::NAME
     */
    public function getStaticName()
    {
        $this::$staticName = $this::NAME;
        parent::getStaticName();
    }
}

$foo = new Foo; //outputs Foo
$bar = new Bar; //outputs FooBar
$foo->getStaticName(); //outputs Foo
$bar->getStaticName(); //outputs FooBar
$foo->getStaticName(); //outputs FooBar

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 kebalikan dari $this::NAME;

7
fyrye

Saya mengalami pertanyaan yang sama dan jawabannya adalah:

  • $ this membutuhkan turunan kelas
  • self :: tidak

Setiap kali Anda menggunakan metode statis atau atribut statis dan ingin memanggil mereka tanpa memiliki objek kelas instantiated Anda perlu menggunakan self :: untuk memanggil mereka , karena $ this selalu membutuhkan objek yang akan dibuat.

5
Mike

Gunakan self jika Anda ingin memanggil metode kelas tanpa membuat objek/instance dari kelas itu, sehingga menghemat RAM (kadang-kadang menggunakan diri untuk tujuan itu). Dengan kata lain, sebenarnya memanggil metode secara statis. Gunakan this untuk perspektif objek.

5
minhajul

Kasus 1: Gunakan self dapat digunakan untuk konstanta kelas

  class classA {
 const FIXED_NUMBER = 4; 
 mandiri :: 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; 
} 
} 
2
li bing zhao

Menurut php.net ada tiga kata kunci khusus dalam konteks ini: self, parent dan static Mereka digunakan untuk mengakses properti atau metode dari dalam definisi kelas.

$this, di sisi lain, digunakan untuk memanggil instance dan metode dari kelas mana pun selama kelas itu dapat diakses.

1
Fil