


Polimorfisme Subtipe - Pelaksanaan Tukar pada Runtime
mata teras
- polimorfisme subtipe dalam reka bentuk berorientasikan objek merujuk kepada keupayaan sistem untuk menentukan satu set kontrak atau antara muka, dan kemudian melaksanakannya dengan subtipe yang berbeza. Ini adalah penting untuk mereka bentuk sistem berskala yang boleh menggunakan kontrak tertentu tanpa memeriksa sama ada pelaksana berada dalam jenis yang diharapkan.
- Artikel ini menunjukkan penggunaan polimorfisme subtype dengan membangunkan komponen cache yang boleh dimasukkan yang boleh diperluaskan untuk memenuhi keperluan pengguna dengan membangunkan pemandu cache tambahan.
- Ciri utama komponen cache adalah keupayaannya untuk menukar pemacu cache yang berbeza pada masa runtime tanpa mengubah sebarang kod klien. Ini dicapai dengan menentukan kontrak cache yang kemudian diikuti oleh pelaksanaan yang berbeza, dengan itu mengambil kesempatan daripada polimorfisme.
- Komponen cache boleh menukar backends pada masa runtime, menonjolkan kepentingan polimorfisme dalam merancang modul yang sangat dihancurkan. Ini membolehkan penyambungan semula mudah pada masa runtime tanpa menyebabkan kelemahan atau isu berkaitan tegar di bahagian lain sistem.
- Polimorfisme subtipe bukan sahaja menjadikan sistem lebih ortogonal dan lebih mudah untuk skala, tetapi juga kurang cenderung untuk melanggar paradigma teras seperti prinsip terbuka/tertutup dan prinsip "pengaturcaraan berorientasikan antara muka". Ia adalah aspek asas pengaturcaraan berorientasikan objek yang membolehkan fleksibiliti dan kebolehgunaan semula kod.
Ramai orang boleh meragui korelasi antara warisan dan polimorfisme dalam reka bentuk berorientasikan objek? Mungkin sedikit, kebanyakan mereka mungkin disebabkan oleh kejahilan atau pemikiran sempit. Tetapi ada masalah kecil di sini yang tidak boleh diabaikan. Walaupun mudah untuk memahami logik warisan, perkara menjadi lebih sukar apabila membincangkan butiran polimorfisme. Istilah "polimorfisme" adalah menakutkan dengan sendirinya, dengan definisi akademiknya penuh dengan perspektif yang berbeza, yang menjadikannya lebih sukar untuk memahami apa yang sebenarnya di belakangnya. Konsep periferal seperti polimorfisme parameter dan polimorfisme ad hoc (biasanya dilaksanakan dengan kaedah override/overload) mempunyai aplikasi yang penting dalam beberapa bahasa pengaturcaraan, tetapi dalam reka bentuk, mereka boleh mengambil kontrak tertentu (bacaan) apabila abstrak) harus ditinggalkan tanpa memeriksa sama ada pelaksana adalah jenis yang diharapkan. Singkatnya, kebanyakan masa, apa-apa rujukan umum terhadap polimorfisme dalam pengaturcaraan berorientasikan objek secara tersirat dianggap sebagai keupayaan sistem-eksplisit yang digunakan untuk menentukan satu set kontrak atau antara muka yang atau antara muka diikuti oleh pelaksanaan yang berbeza. Polimorfisme "kanonik" ini sering dirujuk sebagai polimorfisme subtipe, kerana pelaksana antara muka dianggap sebagai subtipe mereka, tanpa mengira sama ada terdapat hierarki sebenar. Seperti yang dijangkakan, memahami sifat polimorfisme hanya separuh daripada proses pembelajaran; "Kod" (dalam banyak kes, ia adalah eufemisme yang murah untuk kod mainan). Dalam artikel ini, saya akan menunjukkan kepada anda bagaimana untuk memanfaatkan manfaat yang disediakan oleh polimorfisme dengan membangunkan komponen cache yang boleh dimasukkan. Fungsi teras kemudiannya boleh diperluaskan untuk memenuhi keperluan anda dengan membangunkan pemandu cache tambahan.
Tentukan antara muka dan pelaksanaan komponen
Menu pilihan untuk dipilih adalah tidak hadir ketika membina komponen cache yang boleh diperluaskan (jika anda ragu -ragu tentang ini, lihat saja apa yang ada di sebalik kerangka popular). Walau bagaimanapun, di sini, komponen yang saya berikan mempunyai keupayaan pintar untuk menukar pemandu cache yang berbeza pada masa runtime tanpa mengubah suai kod pelanggan. Jadi, bagaimana anda boleh melakukan ini tanpa banyak usaha semasa proses pembangunan? Nah, langkah pertama adalah ... Ya, tentukan kontrak cache terpencil yang akan diikuti oleh pelaksanaan yang berbeza kemudian, dengan itu memanfaatkan manfaat polimorfisme. Pada tahap yang paling asas, kontrak di atas adalah seperti berikut:
<?php namespace LibraryCache; interface CacheInterface { public function set($id, $data); public function get($id); public function delete($id); public function exists($id); }
CacheInterface
adalah kontrak rangka yang abstrak tingkah laku elemen cache biasa. Dengan antara muka, anda boleh dengan mudah membuat beberapa pelaksanaan cache tertentu yang mematuhi kontrak mereka. Oleh kerana saya ingin memastikan ia mudah dan mudah difahami, pemacu cache yang saya sediakan akan menjadi duo tanpa lemak: yang pertama menggunakan sistem fail sebagai backend asas untuk cache/mendapatkan data, sementara yang kedua menggunakan lanjutan APC Di belakang tabir. Berikut adalah pelaksanaan cache berasaskan fail:
<?php namespace LibraryCache; class FileCache implements CacheInterface { const DEFAULT_CACHE_DIRECTORY = 'Cache/'; private $cacheDir; public function __construct($cacheDir = self::DEFAULT_CACHE_DIRECTORY) { $this->setCacheDir($cacheDir); } public function setCacheDir($cacheDir) { if (!is_dir($cacheDir)) { if (!mkdir($cacheDir, 0644)) { throw InvalidArgumentException('The cache directory is invalid.'); } } $this->cacheDir = $cacheDir; return $this; } public function set($id, $data) { if (!file_put_contents($this->cacheDir . $id, serialize($data), LOCK_EX)) { throw new RuntimeException("Unable to cache the data with ID '$id'."); } return $this; } public function get($id) { if (!$data = unserialize(@file_get_contents($this->cacheDir . $id, false))) { throw new RuntimeException("Unable to get the data with ID '$id'."); } return $data; } public function delete($id) { if (!@unlink($this->cacheDir . $id)) { throw new RuntimeException("Unable to delete the data with ID '$id'."); } return $this; } public function exists($id) { return file_exists($this->cacheDir . $id); } }
. Walaupun keupayaan ini manis dan menawan, untuk bahagiannya, saya tidak akan menghargai ia memandangkan matlamat di sini adalah untuk membuat komponen cache yang boleh menukar backends pada masa runtime. Marilah kita berusaha untuk tujuan pengajaran dan membawa satu lagi pelaksanaan yang diselaraskan FileCache
ke kehidupan. Pelaksanaan berikut mematuhi kontrak antara muka, tetapi kali ini dengan menggunakan APC untuk memperluaskan kaedah bundling: CacheInterface
CacheInterface
Kelas
<?php namespace LibraryCache; class ApcCache implements CacheInterface { public function set($id, $data, $lifeTime = 0) { if (!apc_store($id, $data, (int) $lifeTime)) { throw new RuntimeException("Unable to cache the data with ID '$id'."); } } public function get($id) { if (!$data = apc_fetch($id)) { throw new RuntimeException("Unable to get the data with ID '$id'."); } return $data; } public function delete($id) { if (!apc_delete($id)) { throw new RuntimeException("Unable to delete the data with ID '$id'."); } } public function exists($id) { return apc_exists($id); } }
. Walau bagaimanapun, saya harus menekankan bahawa polimorfisme subtipe sebenar dicapai dengan melaksanakan kontrak yang ditakrifkan melalui pembinaan antara muka, yang merupakan pendekatan yang sangat biasa. Walau bagaimanapun, tiada apa yang boleh menghalang anda daripada menjadi kurang ortodoks dan mendapatkan hasil yang sama dengan menukar antara muka yang diisytiharkan sebagai satu set kaedah abstrak (terletak di kelas abstrak). Sekiranya anda merasa berisiko dan ingin pergi ke laluan itu, anda boleh membina semula kontrak dan pelaksanaan yang sepadan seperti berikut: ApcCache
<?php namespace LibraryCache; interface CacheInterface { public function set($id, $data); public function get($id); public function delete($id); public function exists($id); }
<?php namespace LibraryCache; class FileCache implements CacheInterface { const DEFAULT_CACHE_DIRECTORY = 'Cache/'; private $cacheDir; public function __construct($cacheDir = self::DEFAULT_CACHE_DIRECTORY) { $this->setCacheDir($cacheDir); } public function setCacheDir($cacheDir) { if (!is_dir($cacheDir)) { if (!mkdir($cacheDir, 0644)) { throw InvalidArgumentException('The cache directory is invalid.'); } } $this->cacheDir = $cacheDir; return $this; } public function set($id, $data) { if (!file_put_contents($this->cacheDir . $id, serialize($data), LOCK_EX)) { throw new RuntimeException("Unable to cache the data with ID '$id'."); } return $this; } public function get($id) { if (!$data = unserialize(@file_get_contents($this->cacheDir . $id, false))) { throw new RuntimeException("Unable to get the data with ID '$id'."); } return $data; } public function delete($id) { if (!@unlink($this->cacheDir . $id)) { throw new RuntimeException("Unable to delete the data with ID '$id'."); } return $this; } public function exists($id) { return file_exists($this->cacheDir . $id); } }
<?php namespace LibraryCache; class ApcCache implements CacheInterface { public function set($id, $data, $lifeTime = 0) { if (!apc_store($id, $data, (int) $lifeTime)) { throw new RuntimeException("Unable to cache the data with ID '$id'."); } } public function get($id) { if (!$data = apc_fetch($id)) { throw new RuntimeException("Unable to get the data with ID '$id'."); } return $data; } public function delete($id) { if (!apc_delete($id)) { throw new RuntimeException("Unable to delete the data with ID '$id'."); } } public function exists($id) { return apc_exists($id); } }
Dari atas ke bawah, ini memang pendekatan polimorfik, yang bertentangan dengan kaedah yang telah dibincangkan sebelumnya. Secara peribadi, ini hanya pernyataan peribadi saya, saya lebih suka menggunakan antara muka membina untuk menentukan kontrak dan menggunakan kelas abstrak hanya apabila merangkumi pelaksanaan boilerplate yang dikongsi oleh beberapa subtipe. Anda boleh memilih kaedah yang paling sesuai dengan keperluan anda. Pada ketika ini, saya dapat meletakkan tirai, menulis beberapa komen mewah yang mewah, membanggakan tentang kemahiran pengekodan kami yang mengagumkan, dan membual tentang fleksibiliti komponen cache kami, tetapi itu akan menjadi slouch kepada kami. Apabila terdapat kod klien yang boleh menggunakan pelbagai pelaksanaan, polimorfisme mempamerkan aspek yang paling menggoda tanpa memeriksa sama ada pelaksanaan ini adalah contoh beberapa jenis, selagi mereka memenuhi kontrak yang diharapkan. Oleh itu, mari kita mendedahkan aspek dengan menghubungkan komponen cache ke kelas pandangan pelanggan asas, yang akan membolehkan kita melakukan beberapa caching HTML yang kemas dengan mudah.
Letakkan pemacu cache ke dalam penggunaan
output HTML caching melalui modul cache contoh kami sangat mudah dan saya akan menyimpan penjelasan yang panjang pada masa lain. Keseluruhan proses cache dapat dipermudahkan ke dalam kelas pandangan yang mudah, sama seperti yang berikut:
<?php namespace LibraryCache; abstract class AbstractCache { abstract public function set($id, $data); abstract public function get($id); abstract public function delete($id); abstract public function exists($id); }
<?php namespace LibraryCache; class FileCache extends AbstractCache { // the same implementation goes here }
dan CacheInterface
kaedah. Memandangkan tanggungjawab kaedah terakhir adalah untuk menyingkirkan templat pandangan selepas ia ditolak ke penampan output, lebih baik untuk memanfaatkan keupayaan dan cache keseluruhan dokumen HTML. Anggapkan bahawa templat lalai pandangan mempunyai struktur berikut: render()
<?php namespace LibraryCache; class ApcCache extends AbstractCache { // the same implementation goes here }
ke pandangan: ApcCache
<?php namespace LibraryView; interface ViewInterface { public function setTemplate($template); public function __set($field, $value); public function __get($field); public function render(); }
<?php namespace LibraryView; use LibraryCacheCacheInterface; class View implements ViewInterface { const DEFAULT_TEMPLATE = 'default'; private $template; private $fields = array(); private $cache; public function __construct(CacheInterface $cache, $template = self::DEFAULT_TEMPLATE) { $this->cache = $cache; $this->setTemplate($template); } public function setTemplate($template) { $template = $template . '.php'; if (!is_file($template) || !is_readable($template)) { throw new InvalidArgumentException( "The template '$template' is invalid."); } $this->template = $template; return $this; } public function __set($name, $value) { $this->fields[$name] = $value; return $this; } public function __get($name) { if (!isset($this->fields[$name])) { throw new InvalidArgumentException( "Unable to get the field '$field'."); } return $this->fields[$name]; } public function render() { try { if (!$this->cache->exists($this->template)) { extract($this->fields); ob_start(); include $this->template; $this->cache->set($this->template, ob_get_clean()); } return $this->cache->get($this->template); } catch (RuntimeException $e) { throw new Exception($e->getMessage()); } } }
Kesimpulan
Polymorphism memang salah satu perkara yang baik dalam hidup, dan apabila anda memahaminya, ia membuat anda tertanya -tanya bagaimana anda boleh lakukan tanpa kesnya berterusan selama sekian lama. Sistem polimorfik sememangnya lebih ortogonal, lebih mudah untuk skala, dan kurang terdedah kepada melanggar paradigma teras seperti prinsip terbuka/tertutup dan prinsip pengaturcaraan berorientasikan antara muka yang bijak. Walaupun agak primitif, modul cache kami adalah contoh yang menonjol dari kelebihan ini. Sekiranya anda tidak memaklumkan permohonan anda untuk memanfaatkan manfaat polimorfisme, anda akan lebih cepat tergesa -gesa kerana anda terlepas jackpot! gambar dari Fotolia
Soalan Lazim Mengenai Polymorphisms Subtipe (FAQ)
polimorfisme subtipe, juga dikenali sebagai polimorfisme inklusi, adalah satu bentuk polimorfisme di mana nama mewakili contoh -contoh pelbagai kategori yang dikaitkan dengan superclass awam. Polimorfisme parameter, sebaliknya, membolehkan fungsi atau jenis data untuk memproses nilai dengan cara yang sama tanpa bergantung pada jenisnya. Polimorfisme parameter adalah cara untuk membuat bahasa lebih ekspresif sambil mengekalkan keselamatan jenis statik penuh.
Bagaimana polimorfisme subtipe berfungsi di Java?
Di Java, polimorfisme subtipe dicapai dengan menggunakan warisan dan antara muka. Pembolehubah rujukan superclass boleh menunjuk kepada objek subclass. Ini membolehkan Java menentukan kaedah mana yang hendak dipanggil pada masa runtime, yang dipanggil penjadualan kaedah dinamik. Ia adalah salah satu ciri kuat Java yang membolehkannya menyokong polimorfisme dinamik.
Bolehkah anda memberikan contoh polimorfisme subtipe?
Sudah tentu, mari kita pertimbangkan contoh mudah di Java. Katakan kita mempunyai superclass yang dipanggil "haiwan" dan dua subclass "anjing" dan "kucing". Kedua -dua kelas "anjing" dan "kucing" menulis semula kaedah "bunyi" kelas "haiwan". Sekarang, jika kita membuat rujukan "haiwan" yang menunjuk kepada objek "anjing" atau "kucing" dan panggil kaedah "bunyi", Java akan membuat keputusan pada runtime kaedah "bunyi" kelas yang hendak dipanggil. Ini adalah contoh polimorfisme subtipe.
Apakah kepentingan polimorfisme subtipe dalam pengaturcaraan?
polimorfisme subtipe adalah aspek asas pengaturcaraan berorientasikan objek. Ia membolehkan fleksibiliti dan kebolehgunaan semula kod. Menggunakan polimorfisme subtipe, anda boleh merancang antara muka yang sama untuk satu set kelas dan kemudian menggunakan antara muka ini untuk berinteraksi dengan objek kelas tersebut dengan cara yang bersatu. Ini akan menghasilkan lebih bersih, lebih intuitif dan lebih mudah untuk mengekalkan kod.
Apakah hubungan antara polimorfisme subtipe dan prinsip penggantian Liskov?
Prinsip Penggantian Liskov (LSP) adalah prinsip reka bentuk berorientasikan objek yang menyatakan bahawa jika program menggunakan kelas asas, ia sepatutnya dapat menggunakan mana-mana subkelasnya tanpa program yang mengetahui. Dalam erti kata lain, objek superclass harus dapat digantikan oleh objek subclass tanpa menjejaskan ketepatan program. Polimorfisme subtipe adalah aplikasi langsung LSP.
Adakah semua bahasa pengaturcaraan menyokong polimorfisme subtipe?
Tidak, tidak semua bahasa pengaturcaraan menyokong polimorfisme subtipe. Ini terutamanya ciri bahasa pengaturcaraan berorientasikan objek yang ditaip secara statik seperti Java, C, dan C#. Bahasa yang ditaip secara dinamik seperti Python dan JavaScript mempunyai bentuk polimorfisme yang berbeza, yang dipanggil jenis itik.
Apakah perbezaan antara polimorfisme statik dan polimorfisme dinamik?
Polimorfisme statik, juga dikenali sebagai polimorfisme kompilasi masa, dicapai melalui kaedah yang berlebihan. Keputusan mengenai kaedah yang hendak dipanggil dibuat pada masa penyusunan. Sebaliknya, polimorfisme dinamik, yang juga dikenali sebagai polimorfisme runtime, dilaksanakan melalui penulisan semula kaedah. Keputusan mengenai kaedah yang hendak dipanggil dibuat pada masa runtime. Polimorfisme subtipe adalah polimorfisme yang dinamik.
Bolehkah anda menerangkan konsep penukaran dalam polimorfisme subtipe?
Upconversion adalah proses merawat objek kelas yang diperolehi sebagai objek kelas asas. Ia adalah aspek utama polimorfisme subtipe. Apabila anda menaikkan objek kelas yang diperoleh, anda boleh memanggil sebarang kaedah yang ditakrifkan dalam kelas asas. Walau bagaimanapun, jika kaedah itu ditulis semula dalam kelas yang diperolehi, versi penulisan semula akan dipanggil.
Apakah penukaran dalam konteks polimorfisme subtipe?
penukaran turun adalah bertentangan dengan penukaran UP. Ia adalah proses menukarkan objek superclass ke dalam subkelas. Apabila anda perlu mengakses kaedah yang hanya wujud dalam subkelas, anda boleh menggunakan penukaran bawah. Walau bagaimanapun, downconversion boleh berbahaya kerana ia boleh menyebabkan ClassCastException jika objek yang ditukar sebenarnya tidak mempunyai jenis yang anda bertukar.
Bagaimanakah polimorfisme subtipe menggalakkan kebolehgunaan kod?
polimorfisme subtipe membolehkan kita menulis lebih banyak kod umum dan boleh diguna semula. Dengan menggunakan rujukan superclass untuk berinteraksi dengan objek subclass, kita boleh menulis kod untuk pelbagai objek selagi mereka semua tergolong dalam subclass superclass yang sama. Ini bermakna kita boleh menambah subkelas baru tanpa mengubah kod yang menggunakan superclass, yang menjadikan kod kita lebih fleksibel dan lebih mudah untuk dikekalkan.
Atas ialah kandungan terperinci Polimorfisme Subtipe - Pelaksanaan Tukar pada Runtime. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Alipay Php ...

JWT adalah standard terbuka berdasarkan JSON, yang digunakan untuk menghantar maklumat secara selamat antara pihak, terutamanya untuk pengesahan identiti dan pertukaran maklumat. 1. JWT terdiri daripada tiga bahagian: header, muatan dan tandatangan. 2. Prinsip kerja JWT termasuk tiga langkah: menjana JWT, mengesahkan JWT dan muatan parsing. 3. Apabila menggunakan JWT untuk pengesahan di PHP, JWT boleh dijana dan disahkan, dan peranan pengguna dan maklumat kebenaran boleh dimasukkan dalam penggunaan lanjutan. 4. Kesilapan umum termasuk kegagalan pengesahan tandatangan, tamat tempoh, dan muatan besar. Kemahiran penyahpepijatan termasuk menggunakan alat debugging dan pembalakan. 5. Pengoptimuman prestasi dan amalan terbaik termasuk menggunakan algoritma tandatangan yang sesuai, menetapkan tempoh kesahihan dengan munasabah,

Sesi rampasan boleh dicapai melalui langkah -langkah berikut: 1. Dapatkan ID Sesi, 2. Gunakan ID Sesi, 3. Simpan sesi aktif. Kaedah untuk mengelakkan rampasan sesi dalam PHP termasuk: 1. Gunakan fungsi Sesi_Regenerate_ID () untuk menjana semula ID Sesi, 2. Data sesi stor melalui pangkalan data, 3.

Penerapan prinsip pepejal dalam pembangunan PHP termasuk: 1. Prinsip Tanggungjawab Tunggal (SRP): Setiap kelas bertanggungjawab untuk hanya satu fungsi. 2. Prinsip Terbuka dan Tutup (OCP): Perubahan dicapai melalui lanjutan dan bukannya pengubahsuaian. 3. Prinsip Penggantian Lisch (LSP): Subkelas boleh menggantikan kelas asas tanpa menjejaskan ketepatan program. 4. Prinsip Pengasingan Antara Muka (ISP): Gunakan antara muka halus untuk mengelakkan kebergantungan dan kaedah yang tidak digunakan. 5. Prinsip Inversi Ketergantungan (DIP): Modul peringkat tinggi dan rendah bergantung kepada abstraksi dan dilaksanakan melalui suntikan ketergantungan.

Bagaimana cara debug mod CLI dalam phpstorm? Semasa membangun dengan PHPStorm, kadang -kadang kita perlu debug PHP dalam mod Interface Line Command (CLI) ...

Artikel membincangkan ciri -ciri keselamatan penting dalam rangka kerja untuk melindungi daripada kelemahan, termasuk pengesahan input, pengesahan, dan kemas kini tetap.

Bagaimana untuk menetapkan keizinan UnixSocket secara automatik selepas sistem dimulakan semula. Setiap kali sistem dimulakan semula, kita perlu melaksanakan perintah berikut untuk mengubahsuai keizinan UnixSocket: sudo ...

Mengikat statik (statik: :) Melaksanakan pengikatan statik lewat (LSB) dalam PHP, yang membolehkan kelas panggilan dirujuk dalam konteks statik dan bukannya menentukan kelas. 1) Proses parsing dilakukan pada masa runtime, 2) Cari kelas panggilan dalam hubungan warisan, 3) ia boleh membawa overhead prestasi.
