Artikel ini akan memberi anda pemahaman yang mendalam tentang generik dalam PHP dan memperkenalkan dua contoh generik saya harap ia akan membantu anda!
Deeper Generics
Saya menunjukkan generik yang sangat membosankan dalam artikel terdahulu saya Contoh, kita akan lakukan lebih baik dalam yang ini.
$users = new Collection<User>();
$slugs = new Collection<string>();
Salin selepas log masuk
Mereka mungkin cara paling mudah untuk menerangkan generik, tetapi mereka juga merupakan contoh yang dibincangkan oleh semua orang semasa membincangkan generik. Orang sering menganggap "generik" dan "koleksi bertaip" sebagai perkara yang sama. Sama sekali tidak begitu. 集合
Jadi mari kita lihat dua lagi contoh.
Ini ialah fungsi yang dipanggil "apl" - jika anda menggunakan rangka kerja seperti Laravel, ia mungkin kelihatan biasa: fungsi ini menerima nama kelas, Dan gunakan bekas bergantung untuk selesaikan contoh kelas itu:
function app(string $className): mixed
{
return Container::get($className);
}
Salin selepas log masuk
Sekarang, anda tidak perlu tahu cara bekas itu berfungsi, yang penting fungsi ini akan memberi anda contoh kelas yang anda minta.
Jadi, pada asasnya, ia adalah fungsi generik; jenis pulangan bergantung pada nama kelas yang anda berikan. Alangkah baiknya jika IDE kami dan penganalisis statik lain juga memahami bahawa jika saya memberikan fungsi ini nama kelas "UserRepository", saya mahukan contoh UserRepository dikembalikan dan tidak ada yang lain:
function app(string $className): mixed
{ /* … */ }
app(UserRepository::class); // ?
Salin selepas log masuk
Nah, generik membenarkan kita untuk berbuat demikian.
Saya fikir sekarang adalah masa yang baik untuk menyatakan bahawa saya telah menyimpan rahsia, seperti: Saya telah menyebut dalam catatan saya sebelum ini bahawa generik tidak wujud dalam PHP, itu tidak sepenuhnya benar. Semua penganalisis statik di luar sana - alat yang membaca kod tanpa menjalankannya, alat seperti IDE anda - mereka membenarkan penggunaan komen blok dokumen untuk generik:
/**
* @template Type
* @param class-string<Type> $className
* @return Type
*/
function app(string $className): mixed
{ /* … */ }
Salin selepas log masuk
Diakui: Ini bukan sintaks yang paling sempurna, semua penganalisis statik bergantung pada protokol mudah, iaitu tiada sintaks kanonik rasmi bagaimanapun: ia berfungsi. Tiga daripada penganalisis statik terbesar di dunia PHP: PhpStorm, Psalm dan PhpStan, semuanya memahami sintaks ini sedikit sebanyak.
IDE seperti PhpStorm menggunakannya untuk memberikan maklum balas kepada pengaturcara semasa mereka menulis kod, manakala alatan seperti Psalm dan PhpStan menggunakannya untuk menganalisis secara pukal asas kod anda dan mengesan potensi pepijat, Terutamanya berdasarkan definisi jenis.
Jadi sebenarnya, kita boleh membina fungsi
ini supaya alat kita tidak lagi berjalan dalam gelap. Sudah tentu, PHP sendiri tidak dapat menjamin bahawa jenis pulangan adalah betul, kerana PHP tidak akan menaip semak fungsi semasa runtime bagaimanapun, jika kita boleh mempercayai bahawa penganalisis statik kami adalah betul, maka apabila menjalankannya, perenggan ini Terdapat kod yang sangat sedikit; - tiada peluang gangguan. app
Ini adalah kuasa analisis statik yang luar biasa: kami sebenarnya boleh memastikan, tanpa menjalankan kod kami bahawa kebanyakannya akan berfungsi seperti yang diharapkan. Semua ini boleh dilakukan terima kasih kepada jenis - termasuk generik.
Mari kita lihat contoh yang lebih kompleks:
Attributes::in(MyController::class)
->filter(RouteAttribute::class)
->newInstance()
->
Salin selepas log masuk
Di sini kita mempunyai kelas yang boleh "mempertanyakan" sifat dan membuat seketika mereka. Saya dapati kelas pembantu ini sangat berguna jika anda telah menggunakan sifat sebelum mengetahui bahawa API pantulan mereka agak bertele-tele.
Apabila kami menggunakan kaedah
, kami memberikannya nama kelas untuk sifat itu; kemudian memanggil kaedah filter
, kami tahu bahawa hasilnya akan menjadi contoh kelas penapis kami. Sekali lagi: adalah bagus jika IDE kami memahami perkara yang kami bincangkan. newInstance
Anda telah menekanya: Generik membenarkan kami melakukan ini:
/** @template AttributeType */
class Attributes
{
/**
* @template InputType
* @param class-string<InputType> $className
* @return self<InputType>
*/
public function filter(string $className): self
{ /* … */ }
/**
* @return AttributeType
*/
public function newInstance(): mixed
{ /* … */ }
// …
}
Salin selepas log masuk
Saya harap anda mula melihat kuasa maklumat jenis mudah. Beberapa tahun yang lalu saya memerlukan pemalam IDE untuk membuat cerapan ini berfungsi, kini saya hanya perlu menambah beberapa jenis maklumat.
Walau bagaimanapun, contoh terbaharu ini tidak hanya bergantung pada generik, terdapat satu lagi bahagian yang sama pentingnya. Jenis inferens: Keupayaan penganalisis statik untuk "meneka" - atau menentukan dengan pasti - jenis tanpa pengguna menyatakannya. Itulah yang berlaku dengan anotasi seperti rentetan di sana. IDE kami dapat mengenali input yang kami sediakan untuk fungsi ini sebagai nama kelas dan membuat kesimpulan jenis sebagai jenis generik.
Jadi, semuanya telah diselesaikan, betul: Terdapat generik dalam PHP dan semua penganalisis statik utama tahu cara menggunakannya. Nah...ada beberapa kaveat.
Pertama sekali, tiada spesifikasi rasmi tentang rupa generik, kini setiap penganalisis statik boleh menggunakan sintaks mereka sendiri pada masa ini, mereka telah bersetuju dengan salah satu daripadanya; .
Kedua: Sekatan dokumen adalah sub-optimum pada pendapat saya. Mereka berasa kurang penting dalam asas kod kami. Sudah tentu, anotasi generik hanya memberikan cerapan statik dan tiada fungsi masa jalan, tetapi kami telah melihat kuasa analisis statik walaupun tanpa pemeriksaan jenis masa jalan. Saya fikir adalah tidak adil untuk menganggap maklumat jenis sebagai "komen dokumentasi", ia tidak menyampaikan kepentingan jenis ini dalam kod kami. Itulah sebabnya kami mendapat atribut dalam PHP8: semua kefungsian yang disediakan oleh atribut, adalah mungkin dalam ulasan docblock, tetapi ia tidak cukup baik. Perkara yang sama berlaku untuk generik.
Nota akhir: tanpa spesifikasi yang betul, ketiga-tiga penganalisis statik utama mempunyai perbezaan antara pelaksanaan generiknya. PhpStorm adalah yang paling kurang pada masa ini. Sebaik-baiknya, akan ada spesifikasi rasmi dari dalam PHP. Tetapi belum ada yang rasmi lagi.
Ini ialah sebab utama mengapa saya fikir ia berbaloi untuk melaburkan masa dalam penyelesaian yang lebih tahan lama dan lebih mampan. Jadi mengapa PHP belum mempunyai generik yang betul? Mengapa kita bergantung pada bahagian dokumentasi tanpa spesifikasi yang jelas?
Alamat asal: https://stitcher.io/blog/generics-in-php-2
Alamat terjemahan: https://learnku.com/php/t/ 66484
Disyorkan: "Tutorial Video PHP"
Atas ialah kandungan terperinci Ketahui lebih lanjut tentang generik dalam PHP dengan contoh. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!