2009-12-09 15 views
5

Muhtemelen ayrımcı bir birliktelik kullanılarak, F # 'de birden fazla kalıtım düzeyini modellemek için önerilen bir yol var mı?Ayırımcı sendikalar kullanarak birden fazla kalıtım düzeyinin modellenmesi

C# Aşağıdaki gibi bir şey alarak: Ben F # yaptık

class Expr { } 
class SourceExpr : Expr { } 
class JoinExpr : SourceExpr { } 
class TableExpr : SourceExpr { } 

:

type SourceExpr = 
    | Join of JoinExpr 
    | Table of TableExpr 

type Expr = 
    | Source of SourceExpr 
    | ... 

daha iyi bir yolu var mı? Bu, miras olarak aynı polimorfik davranışı sağlıyor mu?

cevap

8

Daha fazla bilgi olmaksızın burada çok kuralcı olmak zor. Ne yapmaya çalıştığınıza bağlı olarak, bir sınıf hiyerarşisi veya ayrımcı bir sendika (DU) kullanmak daha mantıklı olabilir. En yaygın/gizli satışlar, sınıf hiyerarşilerinin 'açık' iken, DU'lar 'kapalı' dır. Yani, bir sınıf hiyerarşisine kolayca yeni türler ekleyebilirsiniz, ancak yeni bir işlem eklemek (temel sınıfta soyut yöntem) mevcut tüm sınıfları değiştirmeyi gerektirir. Aksine, DU'lerle kolayca yeni bir işlem ekleyebilirsiniz (bu model, veri türü üzerinden eşleşir), ancak yeni bir durum (alt sınıf) eklemek için, türü yeniden tanımlamanız ve yeni durumla başa çıkmak için mevcut tüm işlemleri güncellemeniz gerekir. . (Bu bazen "ekspresyon sorunu" olarak adlandırılır).

DU'lar için iyi tipik bir örneği bir derleyici; Dil ve ağaç yapısının sabit olduğu bir dilde özet sözdizim ağacınız var, ancak derleyicide birçok farklı ağaç dönüşümü işlemine sahip olabilirsiniz. Sınıf hiyerarşileri için iyi olan tipik bir örnek UI çerçevelerdir; Widget'ların sağlaması gereken tüm işlemleri tanımlayan bazı temel sınıf (lar) ınız var (Draw, Resize, ...) ancak kullanıcılar ekstra yeteneklerle kendi özel alt türlerini ekleyecekler.

+0

Bir ayrıştırıcı üzerinde çalışıyorum, bu yüzden DU'lerin doğru seçim olduğunu düşünüyorum. Fakat başkalarından miras kalan ifadeler var. Hem Kaynaklar hem de bir Katılma veya Tablo kabul etmesi gereken işlevler vardır. Kaynak, bir çok seçenekten biri olan bir Expr'yi kabul etmesi gereken işlevler de vardır. Ben OO terimlerinde düşünemiyorum ama düşünemiyorum, ama aynı tip polimorfik davranışı korurken bu nispeten durağan hiyerarşiyi modellemenin daha iyi bir yolu olup olmadığını merak ediyorum. – Daniel

+0

Tiplerle modellemek iyi çalışır. Aynı şey "olan" iki tür varsa, aralarında ayrım yapan yeni bir tür ekleyin ve bunu kullanın. Tek dezavantajı, daha fazla yapısöküm yapmak zorunda olmanızdır, ancak ihtiyaç duyduğunuz yerde desen eşleştirmesi ve aktif desenler bunu oldukça tolere edebilir. Bunu oldukça karmaşık özyinelemeli türler ve bir FParsec çözümleyici ile yapıyorum ve oldukça iyi çalışıyor. –

0

Eğer C# olduğu gibi F # devralma kullanarak sınıfları modelleyebilirsiniz .... YA ... Eğer göstermek olarak ayrımcılık sendikaları kullanarak gereksinimlerini modelleyebilirsiniz.

Hayır, ayrımcılık sendikalar potansiyel yeni vaka eklerseniz tüm desen maçları değişiklik gerekecek özellikle polimorfik davranış aynı tür, izin vermez.

O olsa avantajları var sahiptir, C# ayrımcılığa uğrayan F # sendikalar ve miras ile kod yazmak eğilimindedir ... .... ben genişletilebilirlik hakkında spesifik bir endişe var SÜRECE.

Eğer discrimated sendikalar ... Eğer havuç ile elma karşılaştırdığınız kullanarak miras herhangi seviyelerini modelleme değildir.

Eğer bunu okumaya kod daha basit hale getirecek düşünüyorum .... ben bağlamda ayrımcılığa birliği gider ... Her iki paradigmaların aynı gereksinimleri modelleyebilirsiniz .... ama bu öznel.

İlgili konular