2010-01-15 28 views
5

Her öğenin bir arabirimi vardır, IItem. Bunun yanı sıra, Öğe'den gelen IDrawableItem olarak bilinen bir arabirim vardır.Döküm ve arabirim kalıtım

Aşağıdaki kod, bir çizilebilir öğeyi çizmeye çalışıyor, ama yapamıyor koleksiyon olarak bu sınıf depolar sadece IItem kabul eder. Bu sınıfa IItem'dan gelen her şeyi ekleyebilirsiniz, ancak diğer yöntemleri kullanarak yalnızca döküm gerçekleştirebilirsiniz.

foreach (var item in Items) { 
    item.Draw();    // The casting would go here. 
} 

Ben as vb dökme ... ama bu kabul edilebilir biliyorum? En iyi uygulama mı?

Sadece bu tür senaryoların üstesinden gelmenin başka yolları olup olmadığını merak ediyorum.

+0

Aşağıdaki kod, çekilebilir bir öğe çizmeye çalışmaktadır, ancak bu sınıftaki koleksiyonlar yalnızca IItem'i kabul edemez. - NİYE YA? Bize tasarım hakkında biraz bilgi verin. Değiştirebilir misin? –

+0

Jason'ın kodu sizi ikileminizden çıkaracak. Sorun, bunun nesneleriniz için doğru tasarım olup olmadığı ve 2 satırlık açıklamadan söylemek gerçekten zor. – hackerhasid

+0

Belki bunun yerine IDrawbleItem s depolayan bir koleksiyon kullanın? –

cevap

11

Kullanım Enumerable.OfType uygulamak Items sadece bu öğeleri ayıklamak IDrawableItem:

:

foreach(var item in Items.OfType<IDrawableItem>()) { 
    item.Draw(); 
} 

Nanook Yukarıdaki kod muhtemelen aşağıdaki kod eşdeğer çevrilecektir yorumlarda sorulan soruyu ele almak

: elbette
foreach(var item in Items) { 
    if(item is IDrawableItem) { 
     ((IDrawable)item).Draw(); 
    } 
} 

, gerçekten şuna benzer perde arkasında bir yineleyici var

public static IEnumerable<T> OfType<T>(this IEnumerable<TSource> source) { 
    if(source == null) { 
     throw new ArgumentNullException("source"); 
    } 
    foreach(TSource item in source) { 
     if(item is T) { 
      yield return (T)item; 
     } 
    } 
} 

Yani, bu gösteriyor muhtemelen sadece bir kez Items yinelemenize olmasıdır. Tabii ki, OfType'un yukarıdaki gibi uygulanmış olmasına gerek yoktur, ancak bu yapılması gereken bir şeydir.

+0

Bu örnek aslında 2 döngü gerçekleştiriyor mu? 1 IDrawableItems'i almak ve diğeri bunlarla döngü yapmak ve Draw'u çağırmak için. Eğer öyleyse, bu çok etkili değildir. – Nanook

+2

Hayır, sonuçları akıtır. –

+0

Nop, öyle değil. Tüm Linq.Enumerable yöntemleri özel bir Enumerator kullanılarak uygulanır. Yukarıdaki kod foreach gibi bir şeye dönüştürülecektir (öğelerdeki var öğe) {item IDrawableItem olarak IDrawableItem getiri döndürme öğesi ise; } – herzmeister

1

İki alternatif çözümler:

  • ayrı koleksiyonunda drawables tutun.
  • IItem için DrawIfPossible() yöntemini ekleyin., Draw() numaralı telefonu aramak için geçersiz kılmalı, diğer IItem() uygulamacıları boş bir uygulamaya sahip olmalıdır.

Açık tür sorgulama, tasarımda yanlış bir şey olabileceğinin işareti olarak kabul edilir.

+0

Dediğim gibi, bu değişmesi muhtemel olan hızlı bir prototiptir. Yine de tasarımla ilgili son noktanızı kabul ediyorum. – Finglas

+0

Eleştirinin anlamı değildi. Tip sorgulamanın gerekli olduğu durumlar vardır. Hızlı kesmeler, "ICastItDownAsNeeded" gibi nesneleri geçiren çerçeveler, vb. –