Anlamsal alan adınızın IS-A ilişkisine sahip olduğu anlaşılıyor, ancak bunu modellemek için alt türler / kalıtım kullanmaktan, özellikle de çalışma zamanı türü yansıması nedeniyle biraz dikkatli olursunuz. Bununla birlikte, yanlış şeyden korktuğunuzu düşünüyorum - altyazı gerçekten tehlikelerle geliyor, ancak çalışma zamanında bir nesneyi sorguladığınız gerçeği sorun değil. Ne demek istediğimi anlayacaksın.
Nesne yönelimli programlama, IS-A ilişkileri nosyonuna oldukça eğildi, tartışmasız olarak çok ciddi bir şekilde eğildi, bu da iki ünlü eleştirel konsepte yol açtı:
Ancak, IS-A ilişkilerine bakmanın belki de bu güçlükleri olmayan başka bir işlevsel programlama tabanlı başka bir yol olduğunu düşünüyorum. İlk olarak, biz bir yaşayacaksın yüzden, bizim programda atlar ve tek boynuzlu modellemek istiyoruz Horseve bir Unicorntür. Bu türlerin değerleri nelerdir? Şunu söyleyebilirim ki:
- Bu türlerin değerleri (sırasıyla) atların ve tek boynuzlu atların temsilleri veya açıklamalarıdır ;
- Bunlar şematik gösterimler veya açıklamalardır; serbest biçimli değillerdir, çok katı kurallara göre inşa edilmişlerdir.
Kulağa açık gelebilir, ancak bence insanların daire elips sorunu gibi konulara girme yollarından biri, bu noktalara yeterince dikkat etmeyerek. Her daire bir elipstir, ancak bu, bir dairenin her şematik tanımının otomatik olarak bir elipsin farklı bir şemaya göre şematik bir açıklaması olduğu anlamına gelmez. Başka bir deyişle, bir dairedir sırf bir elips bir anlamına gelmez Circlebir olduğunu Ellipse, tabiri caizse. Ancak bu demek oluyor ki:
- Bir bulunmaktadır eden toplam fonksiyon bir dönüştürür
Circlebir halinde (şematik daire açıklama) Ellipseaynı daireleri anlatan (bilgi farklı tip);
- Bir daire tanımlayan ve karşılık gelen döndüren bir kısmi fonksiyon vardır .
EllipseCircle
Bu nedenle, işlevsel programlama terimlerinde, Unicorntürünüzün bir alt tür olması gerekmez Horse, sadece aşağıdaki gibi işlemlere ihtiyacınız vardır:
-- Convert any unicorn-description of into a horse-description that
-- describes the same unicorns.
toHorse :: Unicorn -> Horse
-- If the horse described by the given horse-description is a unicorn,
-- then return a unicorn-description of that unicorn, otherwise return
-- nothing.
toUnicorn :: Horse -> Maybe Unicorn
Ve toUnicornbunun tam tersi olması gerekir toHorse:
toUnicorn (toHorse x) = Just x
Haskell'in Maybetürü, diğer dillerin "seçenek" türü dedikleri şeydir. Örneğin, Java 8 Optional<Unicorn>tipi ya bir Unicornya hiçdir. Alternatiflerinizden ikisinin (bir istisna atma veya "varsayılan veya sihirli bir değer" döndürme) seçenek türlerine çok benzer olduğunu unutmayın.
Temel olarak burada yaptığım şey, alt tipler veya kalıtım kullanmadan, IS-A ilişkisini türler ve işlevler açısından yeniden yapılandırmaktır. Bundan uzak tutacağım şey:
- Modelinizin bir
Horsetürü olması gerekiyor ;
HorseTürü ihtiyacı olan herhangi bir değer, bir tek boynuzlu tarif olup açıkça belirlemek için yeterli bilgi kodlamak için;
- Türün bazı işlemlerinin, bu
Horsetür bilgileri Horseistemesi için belirli bir unicorn olup olmadığını gözlemleyebilmesi için bu tür bilgileri açığa çıkarması gerekir ;
- Türün istemcileri,
Horsebu sonraki işlemleri tek boynuzlu atlar ve atlar arasında ayrım yapmak için çalışma zamanında kullanmak zorunda kalacak.
Yani bu temelde bir " Horsetek boynuzlu at olup olmadığını sormak " bir modeldir. Sen bu modele karşı temkinlisin, ama bence yanlış. Size bir Horses listesi verirseniz , söz konusu olanın garanti ettiği şey, listedeki öğelerin tanımladığı şeylerin atlar olduğudur - kaçınılmaz olarak, çalışma zamanında hangisinin tek boynuzlu olduğunu söylemek için bir şeyler yapmanız gerekir. Dolayısıyla, bunun üstesinden gelmek yok, bence - sizin için yapacak işlemleri yapmanız gerekiyor.
Nesne yönelimli programlamada, bunu yapmanın bilinen yolu şudur:
- Bir
Horsetür var;
- Var
Unicornbir alt tipi olarak Horse;
- Belirli
Horsebir zaman olup olmadığını belirleyen, istemci tarafından erişilebilir bir işlem olarak çalışma zamanı türü yansımasını kullanın Unicorn.
Bu, yukarıda sunduğum "şey ve açıklama" açısından bakarken, çok büyük bir zayıflık var:
- Tek
Horseboynuzlu atı tarif eden, ancak bir Unicornörnek olmayan bir örneğiniz varsa?
En başa dönersek, bu bir IS-A ilişkisini modellemek için alt yazı ve alt pencereleri kullanmanın gerçekten korkutucu bir parçası olduğunu düşünüyorum - bir çalışma zamanı kontrolü yapmanız gerekmiyor. Tipografiyi biraz kötüye kullanmak, Horsebunun bir Unicornörnek olup olmadığını sormak Horse, tek boynuzlu at olup olmadığını sormakla eşanlamlı değildir ( Horseaynı zamanda tek boynuzlu at olan bir atın tanımı olup olmadığı ). Programınız, bir kodu tekboynuzlu atı tarif Horseseden bir müşteri kurmaya çalıştığında yapılandıran kodu kapatacak kadar uzun Horsesürmediyse, Unicornsınıf başlatılır. Tecrübelerime göre, nadiren programcılar bunu dikkatlice yaparlar.
Bu yüzden, Horses'yi Unicorns'ye çeviren açık ve aşağı olmayan bir işlemin olduğu yaklaşıma giderdim . Bu, aşağıdaki Horsetürden bir yöntem olabilir :
interface Horse {
// ...
Optional<Unicorn> toUnicorn();
}
... ya da harici bir nesne olabilir ("atın tek boynuzlu at olup olmadığını söyleyen bir at üzerindeki ayrı nesnen"):
class HorseToUnicornCoercion {
Optional<Unicorn> convert(Horse horse) {
// ...
}
}
Bunların arasında seçim yapmak, programınızın nasıl organize edildiğine ilişkin bir konudur - her iki durumda da, işlemimin Horse -> Maybe Unicornyukarıdan eşdeğeri vardır, sadece farklı şekillerde paketliyorsunuzdur (kuşkusuz bu tür işlemlerin ne tür işlemler Horsegerektirdiği üzerinde dalgalanma etkileri olacaktır. müşterilerine göstermek için).