PEMBARUAN : PHP 7.4 sekarang mendukung kovariansi dan pelanggaran yang membahas masalah utama yang diangkat dalam pertanyaan ini.
Saya telah mengalami sesuatu masalah dengan menggunakan tipe return yang mengisyaratkan di PHP 7. Pemahaman saya adalah bahwa mengisyaratkan : self
berarti Anda bermaksud agar kelas pelaksana mengembalikan dirinya sendiri. Oleh karena itu saya menggunakan : self
antarmuka saya untuk menunjukkan itu, tetapi ketika saya mencoba untuk benar-benar menerapkan antarmuka saya mendapat kesalahan kompatibilitas.
Berikut ini adalah demonstrasi sederhana dari masalah yang saya alami:
interface iFoo
{
public function bar (string $baz) : self;
}
class Foo implements iFoo
{
public function bar (string $baz) : self
{
echo $baz . PHP_EOL;
return $this;
}
}
(new Foo ()) -> bar ("Fred")
-> bar ("Wilma")
-> bar ("Barney")
-> bar ("Betty");
Output yang diharapkan adalah:
Fred Wilma Barney Betty
Apa yang sebenarnya saya dapatkan adalah:
PHP Fatal error: Deklarasi Foo :: bar (int $ baz): Foo harus kompatibel dengan iFoo :: bar (int $ baz): iFoo di test.php pada baris 7
Masalahnya adalah Foo adalah implementasi dari iFoo, sejauh yang saya tahu implementasinya harus kompatibel dengan antarmuka yang diberikan. Saya mungkin dapat memperbaiki masalah ini dengan mengubah antarmuka atau kelas pelaksana (atau keduanya) untuk mengembalikan petunjuk antarmuka dengan nama daripada menggunakan self
, tetapi pemahaman saya adalah bahwa secara semantik self
berarti "mengembalikan instance kelas yang baru saja Anda panggil metode ini ". Oleh karena itu mengubahnya ke antarmuka berarti dalam teori bahwa saya dapat mengembalikan contoh apa pun dari sesuatu yang mengimplementasikan antarmuka ketika maksud saya adalah untuk contoh yang dipanggil adalah apa yang akan dikembalikan.
Apakah ini kekeliruan di PHP atau apakah ini keputusan desain yang disengaja? Jika yang pertama, apakah ada kemungkinan melihatnya diperbaiki di PHP 7.1? Jika tidak, lalu apa cara yang benar untuk kembali yang mengisyaratkan bahwa antarmuka Anda mengharapkan Anda untuk mengembalikan contoh yang baru saja Anda panggil metode untuk merangkai?