Ördek yazılan dillerde olağan gibi , Liskov İkame İlkesinin nesnelerin kendilerini denetleyebileceği dillerde gözlenemediğini doğru anladım mı?
Örneğin, Ruby, eğer bir sınıf B
bir sınıftan devralır A
, sonra her nesne x
arasında A
, x.class
dönüş gidiyor A
, ama eğer x
bir amacı B
, x.class
geri gitmiyor A
.
İşte LSP'nin bir açıklaması:
Let q (X) nesneler hakkında bir özellik ispat edilebilir x tipi T . Daha sonra q, (y) nesneler için kanıtlanabilir olmalıdır y Çeşidi S burada G bir alt tipi olan T .
Yani Ruby'de, örneğin,
class T; end
class S < T; end
q (x) = özelliğinin tanığı gibi LSP'yi bu biçimde ihlal etmekx.class.name == 'T'
İlave. Cevap "evet" ise (LSP içgözlemle uyumlu değildir), diğer sorum şu olabilir: muhtemelen bazı ek koşullar altında ve yalnızca özel türlerle dinamik bir dil tutabilecek bazı değiştirilmiş "zayıf" LSP formu var mı? ait özellikleri .
Güncelleme. Referans için, web'de bulduğum başka bir LSP formülasyonu:
İşaretçiler veya temel sınıflara başvurular kullanan işlevler, türetilmiş sınıfların nesnelerini bilmeden kullanabilmelidir.
Ve başka:
S, T'nin beyan edilen bir alt tipi ise, T tipi nesnelerin, T tipi nesneler olarak muamele gördükleri takdirde, T tipi nesnelerin davranması beklendiği için davranmalıdır.
Sonuncusu şu açıklamalara eklenir:
LSP'nin tamamen nesnelerin beklenen davranışı ile ilgili olduğunu unutmayın. Bir kişi LSP'yi ancak nesnelerin beklenen davranışının ne olduğu konusunda açıksa izleyebilir.
Bu orijinalinden daha zayıf gibi gözüküyor ve gözlemlemek mümkün olabilir, ancak bunu resmi olarak görmek istiyorum, özellikle beklenen davranışın ne olduğuna kimin karar verdiğini açıkladı.
Öyleyse LSP, bir programlama dilinde bir çift sınıfın özelliği değil, bir çift sınıfın bir dizi özellikle birlikte, ata sınıfı tarafından memnun mu? Pratik olarak, bu LSP'ye saygı duyan bir alt sınıf (alt sınıf) oluşturmak için, ata sınıfının tüm olası kullanımlarının bilinmesi gerektiği anlamına mı gelir? LSP'ye göre, ata sınıfının herhangi bir alt sınıfla değiştirilmesi gerekiyordu, değil mi?
Güncelleme. Cevabı zaten kabul ettim, ancak soruyu göstermek için Ruby'den bir somut örnek daha eklemek istiyorum. Ruby'de her sınıf, Class
sınıfın sınıfın soyundan gelmesi anlamında bir modüldür Module
. Ancak:
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)