Diri baru vs statis baru

513

Saya mengubah perpustakaan PHP 5.3 untuk bekerja di PHP 5.2. Hal utama yang menghalangi saya adalah penggunaan binding statis akhir seperti return new static($options);, jika saya mengonversikan ini, apakah saya return new self($options)akan mendapatkan hasil yang sama?

Apa perbedaan antara new selfdan new static?

Mike
sumber

Jawaban:

890

apakah saya akan mendapatkan hasil yang sama?

Tidak juga. Saya tidak tahu solusi untuk PHP 5.2.

Apa perbedaan antara new selfdan new static?

selfmerujuk ke kelas yang sama dengan newkata kunci yang sebenarnya ditulis.

static, dalam binding statis akhir PHP 5.3, merujuk ke kelas apa pun dalam hierarki yang Anda panggil metode ini.

Dalam contoh berikut, Bmewarisi kedua metode dari A. The selfDoa terikat untuk Akarena itu didefinisikan dalam Apelaksanaan 's dari metode pertama, sedangkan staticterikat untuk yang disebut kelas (lihat juga get_called_class()).

class A {
    public static function get_self() {
        return new self();
    }

    public static function get_static() {
        return new static();
    }
}

class B extends A {}

echo get_class(B::get_self());  // A
echo get_class(B::get_static()); // B
echo get_class(A::get_self()); // A
echo get_class(A::get_static()); // A
BoltClock
sumber
masuk akal. Saya pikir yang terbaik adalah meneruskan nama kelas ke fungsi yang menggunakan pengikatan statis akhir dan kemudian mengembalikan $ className baru (opsi $);
Mike
12
Anda tidak harus "meneruskan" nama kelas, Anda selalu dapat melakukannya get_called_class(), yang secara efektif sama dengan __CLASS__, tetapi kompatibel dengan LSB.
shadowhand
7
get_called_class tidak ada di <PHP5.3. Oleh karena itu, jika Anda ingin mendapatkan nama kelas dari objek instantiated di PHP5.2 Fungsi ini tidak membantu ketika mencoba mengubah perpustakaan dari PHP 5.3 ke PHP 5.2
txwikinger
2
Fungsi yang disebut sebagai self :: theFunction () berperilaku seperti "Saya akan mengeksekusi dalam konteks kelas yang secara fisik saya milik." dan fungsi yang disebut sebagai static :: theFunction () berperilaku seperti "Saya akan mengeksekusi dalam konteks kelas yang sebenarnya disebut oleh dunia luar". (Dengan asumsi skenario warisan). Terima kasih
Shubhranshu
2
Di kepala saya, saya hanya mengambil apa pun yang intuitif, dan membuatnya berlawanan. Anda akan berpikir berdasarkan penamaan, selfakan kembali dengan sendirinya, dan staticakan mengembalikan sesuatu yang tidak dapat ditimpa ... Tapi lihatlah sebaliknya. Saya tidak pernah berhenti terkesan dengan penamaan, konvensi, dan gaya PHP. -_-
ahnbizcad
23

Jika metode kode ini tidak statis, Anda bisa mendapatkan penyelesaian di 5.2 dengan menggunakan get_class($this).

class A {
    public function create1() {
        $class = get_class($this);
        return new $class();
    }
    public function create2() {
        return new static();
    }
}

class B extends A {

}

$b = new B();
var_dump(get_class($b->create1()), get_class($b->create2()));

Hasil:

string(1) "B"
string(1) "B"
Marius Balčytis
sumber
17
Jika metode ini tidak statis maka binding statis terlambat menjadi sama sekali tidak relevan.
BoltClock
1
Misalnya, Anda dapat menggunakannya dalam metode "salin", di mana objek disalin tanpa menggunakan clone, tetapi hanya dengan membuat ulang dan mengatur properti. $copy = new static(); $copy->set($this->get()); return $copy;
Marius Balcytis
9
@BoltClock Tentunya bukan? Jika Anda memanggil metode statis yang diganti dari dalam metode instance dari subclass, maka pilihan Anda self::atau static::akan mempengaruhi apakah versi kelas dasar atau versi subclass dari metode statis yang digunakan. Dengan tidak adanya alasan untuk berpikir bahwa situasi seperti itu terjadi secara inheren mengindikasikan praktik buruk (dan saya tidak melihat alasan mengapa ini harus terjadi), pilihan antara self::dan static::sama relevan dalam metode non-statis seperti di metode statis. Apakah saya salah memahami komentar Anda, atau salah kami saja?
Mark Amery
4
@ Mark Amery: Hmm saya tidak memikirkan itu. Anda benar sekali. Saya berasumsi bahwa tidak ada metode statis yang akan dipanggil dalam metode contoh yang dimaksud, tetapi berdasarkan contoh Anda, saya dapat melihat bagaimana itu akan menjadi asumsi yang sangat naif.
BoltClock
7

Selain jawaban orang lain:

static :: akan dihitung menggunakan informasi runtime.

Itu berarti Anda tidak dapat menggunakan static::properti kelas karena nilai properti:

Harus dapat dievaluasi pada waktu kompilasi dan tidak boleh bergantung pada informasi run-time.

class Foo {
    public $name = static::class;

}

$Foo = new Foo;
echo $Foo->name; // Fatal error

Menggunakan self::

class Foo {
    public $name = self::class;

}
$Foo = new Foo;
echo $Foo->name; // Foo

Harap dicatat bahwa komentar kesalahan fatal dalam kode yang saya buat tidak menunjukkan di mana kesalahan terjadi, kesalahan terjadi sebelumnya sebelum objek dipakai sebagai @Grapestain yang disebutkan dalam komentar

Hujan
sumber
4
Perhatikan kesalahan dilemparkan pada baris 2 public $name = static::class;, bukan pada baris 7, seperti yang disarankan oleh contoh. Kesalahan mengatakan: "static :: class tidak dapat digunakan untuk resolusi nama kelas waktu kompilasi" yang menunjukkan masalahnya bukan di mana Anda mencoba mengakses bidang $ name, tetapi jauh sebelumnya, pada kompilasi kelas PHP. Jalur 7 (atau 6) tidak akan tercapai dalam contoh pertama.
sbnc.eu
@Gapestain Komentar yang saya buat dalam contoh ini adalah untuk menunjukkan hasil akhir dan bukan untuk menunjukkan di mana kesalahan sebenarnya terjadi. Tapi bagaimanapun, terima kasih sudah menunjukkannya.
Hujan
Benar, saya tidak bermaksud mengkritik, hanya mengklarifikasi apa yang membingungkan saya terlebih dahulu dengan harapan dapat membantu orang lain. Contoh bermanfaat!
sbnc.eu