Apakah saya mengerti benar bahwa Prinsip Pergantian Liskov tidak dapat diamati dalam bahasa di mana objek dapat memeriksa diri mereka sendiri, seperti apa yang biasa dalam bahasa yang diketik bebek?
Misalnya, di Ruby, jika kelas B
mewarisi dari kelas A
, maka untuk setiap objek x
dari A
, x.class
akan kembali A
, tetapi jika x
adalah obyek B
, x.class
tidak akan kembali A
.
Berikut ini adalah pernyataan LSP:
Biarkan q (x) menjadi dibuktikan properti tentang obyek x tipe T . Kemudian q (y) harus dibuktikan untuk benda y tipe S di mana S adalah subtipe dari T .
Jadi di Ruby, misalnya,
class T; end
class S < T; end
melanggar LSP dalam formulir ini, seperti yang disaksikan oleh properti q (x) =x.class.name == 'T'
Tambahan. Jika jawabannya "ya" (LSP tidak sesuai dengan introspeksi), maka pertanyaan saya yang lain adalah: apakah ada beberapa bentuk LSP "lemah" yang dimodifikasi yang dapat digunakan untuk bahasa yang dinamis, mungkin dalam beberapa kondisi tambahan dan hanya dengan jenis khusus dari sifat .
Memperbarui. Untuk referensi, berikut adalah formulasi lain dari LSP yang saya temukan di web:
Fungsi yang menggunakan pointer atau referensi ke kelas dasar harus dapat menggunakan objek dari kelas turunan tanpa menyadarinya.
Dan satu lagi:
Jika S adalah subtipe T yang dinyatakan, objek tipe S harus berperilaku sebagai objek tipe T yang diharapkan berperilaku, jika mereka diperlakukan sebagai objek tipe T.
Yang terakhir dijelaskan dengan:
Perhatikan bahwa LSP adalah semua tentang perilaku objek yang diharapkan. Seseorang hanya dapat mengikuti LSP jika dia jelas tentang apa perilaku objek yang diharapkan.
Ini tampaknya lebih lemah daripada yang asli, dan mungkin dapat diamati, tetapi saya ingin melihatnya diformalkan, khususnya yang menjelaskan siapa yang memutuskan apa perilaku yang diharapkan.
Apakah kemudian LSP bukan properti sepasang kelas dalam bahasa pemrograman, tetapi sepasang kelas bersama-sama dengan serangkaian properti yang diberikan, puas oleh kelas leluhur? Secara praktis, apakah ini berarti bahwa untuk membangun subclass (kelas keturunan) yang menghormati LSP, semua kemungkinan penggunaan kelas leluhur harus diketahui? Menurut LSP, kelas leluhur seharusnya bisa diganti dengan kelas turunan, kan?
Memperbarui. Saya sudah menerima jawabannya, tetapi saya ingin menambahkan satu lagi contoh nyata dari Ruby untuk mengilustrasikan pertanyaan itu. Di Ruby, setiap kelas adalah modul dalam arti bahwa Class
kelas adalah turunan dari Module
kelas. Namun:
class C; end
C.is_a?(Module) # => true
C.class # => Class
Class.superclass # => Module
module M; end
M.class # => Module
o = Object.new
o.extend(M) # ok
o.extend(C) # => TypeError: wrong argument type Class (expected Module)