Muhtemelen ilk önce bir tip ile bir sınıf arasında ayrım yapmak ve sonra alt tipleme ile alt sınıflama arasındaki farka dalmak yararlıdır.
Bu cevabın geri kalanı için, tartışmaya konu olan tiplerin statik tipler olduğunu kabul edeceğim (alt tipleme genellikle statik bir bağlamda ortaya çıktığından).
Bir tür ve sınıf arasındaki farkı göstermek için bir oyuncak sözde kod geliştireceğim çünkü çoğu dil onları en azından kısmen kapsıyor (kısaca değinmek için iyi bir nedenle).
Bir tür ile başlayalım. Tür, kodunuzdaki bir ifade için bir etikettir. Bu etiketin değeri ve diğer etiketlerin değerleriyle tutarlı olup olmadığına (belirli bir sisteme özgü tutarlılık türü için), programınızı çalıştırmadan harici bir programla (typechecker) belirlenebilir. Bu etiketleri özel kılan ve kendi adlarını hak eden şey budur.
Oyuncak dilimizde bunun gibi etiketlerin oluşturulmasına izin verebiliriz.
declare type Int
declare type String
O zaman çeşitli değerleri bu tip olarak etiketleyebiliriz.
0 is of type Int
1 is of type Int
-1 is of type Int
...
"" is of type String
"a" is of type String
"b" is of type String
...
Bu ifadelerle, yazım denetleyicimiz şimdi
0 is of type String
tür sistemimizin gereksinimlerinden biri, her ifadenin benzersiz bir türünün olmasıdır.
Şimdi bunun ne kadar beceriksiz olduğunu ve sınırsız sayıda ifade türü atama konusunda nasıl sorun yaşayacağınızı bir kenara bırakalım. Daha sonra geri dönebiliriz.
Öte yandan, bir sınıf birlikte gruplandırılmış bir yöntem ve alan koleksiyonudur (potansiyel olarak özel veya genel gibi erişim değiştiricilerle).
class StringClass:
defMethod concatenate(otherString): ...
defField size: ...
Bu sınıfın bir örneği, bu yöntem ve alanların önceden tanımlanmış tanımlarını oluşturma veya kullanma yeteneğini kazanır.
Bir sınıfı, bir sınıfın her örneğinin otomatik olarak bu türle etiketleneceği bir türle ilişkilendirmeyi seçebiliriz.
associate StringClass with String
Ancak her türün bir ilişkili sınıfa sahip olması gerekmez.
# Hmm... Doesn't look like there's a class for Int
Ayrıca oyuncak dilimizde her sınıfın bir türünün olmadığı, özellikle de tüm ifadelerimizin türünün olmadığı düşünülebilir. Bazı ifadelerin türleri olsaydı ve bazıları olmasa, ne tür sistem tutarlılık kurallarının görüneceğini hayal etmek biraz daha zor (ama imkansız değil).
Dahası, oyuncak dilimizde bu birlikteliklerin benzersiz olması gerekmez. İki sınıfı aynı tipte ilişkilendirebiliriz.
associate MyCustomStringClass with String
Şimdi yazım denetleyicimizin bir ifadenin değerini izlemesine gerek olmadığını unutmayın (ve çoğu durumda bunu yapmaz veya yapması imkansızdır). Tek bildiği, söylediğiniz etiketler. Daha önce hatırlatmak gerekirse, typechecker ifadelerin yalnızca 0 is of type String
yapay olarak yaratılan tür kuralımız nedeniyle ifadeleri reddedebildi; ifadelerin benzersiz türlere sahip olması gerektiğini ve ifadeyi zaten 0
başka bir şey olarak etiketledik . Bunun değeri hakkında hiçbir özel bilgiye sahip değildi 0
.
Peki ya altyazı? Altyazı, yazım denetlemede sahip olabileceğiniz diğer kuralları gevşeten ortak bir kuralın adıdır. Yani A is subtype of B
, bilgisayar tamircinizin etiketini talep ettiği her yerde B
, o da kabul edecektir A
.
Örneğin, numaralarımız için daha önce sahip olduklarımız yerine aşağıdakileri yapabiliriz.
declare type NaturalNum
declare type Int
NaturalNum is subtype of Int
0 is of type NaturalNum
1 is of type NaturalNum
-1 is of type Int
...
Alt sınıflama, daha önce bildirilmiş yöntemleri ve alanları yeniden kullanmanıza izin veren yeni bir sınıfı bildirmek için kullanılan bir yoldur.
class ExtendedStringClass is subclass of StringClass:
# We get concatenate and size for free!
def addQuestionMark: ...
Biz ortak örneklerini gerekmez ExtendedStringClass
ile String
örneğinde yaptığımız gibi StringClass
bu yepyeni sınıf var sonuçta beri, biz sadece kadar yazma yoktu. Bu , yazım denetleyicisinin bakış ExtendedStringClass
açısından uyuşmayan bir tür vermemize izin verir String
.
Aynı şekilde tamamen yeni bir sınıf oluşturmaya karar verdik NewClass
ve
associate NewClass with String
Artık her örnek , denetleyicinin bakış açısından StringClass
ikame edilebilir NewClass
.
Dolayısıyla teoride alt yazma ve alt sınıflama tamamen farklı şeylerdir. Ama bildiğim hiçbir dilde bu tür ve sınıfları yok aslında bu şekilde işler. Dilimizi parçalamaya başlayalım ve bazı kararlarımızın arkasındaki mantığı açıklayalım.
İlk olarak, teoride tamamen farklı sınıflara aynı tip verilebilse veya bir sınıfa herhangi bir sınıfın örneği olmayan değerlerle aynı türde verilebilse de, bu, typechecker'ın yararını ciddi şekilde engeller. Tipechecker, bir ifade içinde çağırdığınız yöntem veya alanın gerçekten de bu değerde olup olmadığını kontrol etme yeteneğinden etkin bir şekilde etkilenir; bu, muhtemelen bir typechecker. Ne de olsa, bu String
etiketin altındaki değerin kim olduğunu kim bilir ; hiç bir concatenate
metoda sahip olmayan bir şey olabilir, örneğin hiç bir yöntem!
Tamam, öyleyse her sınıfın otomatik olarak aynı sınıfla aynı adda yeni bir tür üreteceğini ve associate
bu türdeki örnekleri olduğunu belirtelim. Bu associate
, StringClass
ve arasındaki farklı isimler kadar iyi kurtulmamızı sağlar String
.
Aynı sebepten dolayı, muhtemelen birinin diğerinin alt sınıfı olduğu iki sınıf türü arasında otomatik olarak bir alt tür ilişkisi kurmak istiyoruz. Tüm alt sınıfların, üst sınıfın yaptığı tüm yöntem ve alanlara sahip olması garanti edildikten sonra, bunun tersi doğru değildir. Bu nedenle, alt sınıf bir tür üst sınıfa ihtiyacınız olduğunda geçebilse de, alt sınıfın türüne ihtiyacınız varsa üst sınıfın türü reddedilmelidir.
Bunu, kullanıcı tarafından tanımlanan tüm değerlerin bir sınıfın örneği olması şartı ile birleştirirseniz, is subclass of
iki katı görev alabilir ve kurtulabilirsiniz is subtype of
.
Bu da bizi popüler statik olarak yazılmış OO dillerinin paylaştığı özelliklere götürüyor. Herhangi bir sınıfla ilişkili olmayan ve kullanıcı tanımlı olmayan bir dizi "ilkel" tip (ör int
. float
, Vb.) Vardır . Daha sonra, otomatik olarak aynı isim tipine sahip ve alt tipleme ile alt sınıflamayı tanımlayan tüm kullanıcı tanımlı sınıflara sahipsiniz.
Yapacağım son not, değerlerin ayrı ayrı ilan edilmesi konusundaki sıkışıklığı etrafında. Çoğu dil, ikisinin oluşturulmasını sınırlar; böylece bir tür bildirimi, aynı zamanda otomatik olarak bu türle etiketlenen tamamen yeni değerler üretme bildirimidir. Örneğin, bir sınıf bildirimi tipik olarak hem türü hem de bu tür değerlerin somutlaştırılmasının bir yolunu yaratır. Bu, bazı tıkanıklıklardan kurtulur ve yapıcıların varlığında, aynı zamanda bir vuruşta tür içeren sonsuz sayıda değer etiketi oluşturmanıza da olanak sağlar.