Delege vs Arayüzler-Başka açıklama var mı?


23

Makaleyi okuduktan sonra - Arayüz Yerine Delege Ne Zaman Kullanmalı (C # Programlama Kılavuzu) , çok açık olmayan (benim için) bulduğum noktaları anlamak için yardıma ihtiyacım var. Bunlar için herhangi bir örnek veya ayrıntılı açıklamalar var mı?

Aşağıdaki durumlarda bir temsilci kullanın:

  • Bir olay tasarım deseni kullanılır.
  • Statik bir yöntemin kapsüllenmesi arzu edilir.
  • Kolay kompozisyon arzu edilir.
  • Bir sınıf, yöntemin birden fazla uygulamasına ihtiyaç duyabilir.

Aşağıdaki durumlarda bir arayüz kullanın:

  • Çağrılabilecek bir grup ilgili yöntem vardır.
  • Bir sınıf sadece yöntemin bir uygulamasına ihtiyaç duyar.

Benim sorularım

  1. Gelecekteki bir tasarım deseni ile ne demek istiyorlar?
  2. Bir temsilci kullanılırsa kompozisyonun kolay olduğu ortaya çıktı?
  3. çağrılabilecek bir grup ilgili yöntem varsa, o zaman arayüzü kullanın-Ne faydası var?
  4. eğer bir sınıf metodun sadece bir uygulamasına ihtiyaç duyuyorsa, kullan-arayüzünü kullanması faydalar açısından nasıl doğrulanır?

Yanıtlar:


11

Gelecekteki bir tasarım deseni ile ne demek istiyorlar?

Büyük olasılıkla , C # 'da temel bir dil yapısı olan gözlemci modelinin ' olaylar ' olarak ortaya çıkan bir uygulamasına atıfta bulunurlar . Olayları dinlemek, bir temsilci asmakla mümkündür. Yam Marcovic'in belirttiği gibi, EventHandlerolaylar için geleneksel temel delege türüdür, ancak herhangi bir delege türü kullanılabilir.

Bir temsilci kullanılırsa kompozisyonun kolay olduğu ortaya çıktı?

Bu muhtemelen sadece delegelerin sunduğu esnekliğe işaret ediyor. Belirli davranışları kolayca 'oluşturabilirsiniz'. Lambdaların yardımı ile bunu yapmak için kullanılan sözdizimi de çok özlüdür. Aşağıdaki örneği düşünün.

class Bunny
{
    Func<bool> _canHop;

    public Bunny( Func<bool> canHop )
    {
        _canHop = canHop;
    }

    public void Hop()
    {
        if ( _canHop() )  Console.WriteLine( "Hop!" );
    }
}

Bunny captiveBunny = new Bunny( () => IsBunnyReleased );
Bunny lazyBunny = new Bunny( () => !IsLazyDay );
Bunny captiveLazyBunny = new Bunny( () => IsBunnyReleased && !IsLazyDay );

Arayüzlere benzer bir şey yapmak, strateji modelini kullanmanızı veya Bunnydaha spesifik tavşanlar uzattığınız (soyut) bir temel sınıfı kullanmanızı gerektirir .

çağrılabilecek bir grup ilgili yöntem varsa, o zaman arayüzü kullanın-Ne faydası var?

Yine, nasıl daha kolay olacağını göstermek için tavşanlar kullanacağım.

interface IAnimal
{
    void Jump();
    void Eat();
    void Poo();
}

class Bunny : IAnimal { ... }
class Chick : IAnimal { ... }

// Using the interface.
IAnimal bunny = new Bunny();
bunny.Jump();  bunny.Eat();  bunny.Poo();
IAnimal chick = new Chick();
chick.Jump();  chick.Eat();  chick.Poo();

// Without the interface.
Action bunnyJump = () => bunny.Jump();
Action bunnyEat = () => bunny.Eat();
Action bunnyPoo = () => bunny.Poo();
bunnyJump(); bunnyEat(); bunnyPoo();
Action chickJump = () => chick.Jump();
Action chickEat = () => chick.Eat();
...

eğer bir sınıf metodun sadece bir uygulamasına ihtiyaç duyuyorsa, kullan-arayüzünü kullanması faydalar açısından nasıl doğrulanır?

Bunun için tavşanlı ilk örneği tekrar düşünün. Sadece bir uygulamaya ihtiyaç varsa - hiçbir özel bileşime gerek kalmaz - bu davranışı bir arabirim olarak gösterebilirsiniz. Asla lambda yapmak zorunda kalmayacaksınız, sadece arayüzü kullanabilirsiniz.

Sonuç

Delegeler daha fazla esneklik sunarken, arayüzler güçlü sözleşmeler yapmanıza yardımcı olur. Dolayısıyla, belirtilen son noktayı buluyorum, "Bir sınıf, yöntemin birden fazla uygulamasına ihtiyaç duyabilir." , şimdiye kadar en alakalı olanı.

Temsilcileri kullanmanın ek bir nedeni, kaynak dosyayı ayarlayamadığınız bir sınıfın sadece bir bölümünü göstermek istediğiniz zamandır.

Böyle bir senaryonun bir örneği (maksimum esneklik, kaynakları değiştirmeye gerek yoktur), sadece iki delegeyi geçerek olası herhangi bir tahsilat için ikili arama algoritmasının bu uygulamasını düşünün .


12

Bir temsilci, tek bir yöntem imzası için bir arabirim gibi bir şeydir, normal bir arabirim gibi açıkça uygulanması gerekmeyen bir şeydir. Kaçak inşa edebilirsiniz.

Bir arayüz sadece bazı sözleşmeleri temsil eden bir dil yapısıdır - "Aşağıdaki yöntemleri ve özellikleri uygun hale getirmeyi garanti ediyorum".

Ayrıca, delegelerin, gözlemci / abone modeline bir çözüm olarak kullanıldığında öncelikli olarak yararlı olduğu konusunda tam olarak hemfikir değilim. Bununla birlikte, "java ayrıntısızlığı sorunu" na zarif bir çözümdür.

Sorularınız için:

1 & 2)

Java'da bir etkinlik sistemi oluşturmak istiyorsanız, etkinliği yaymak için genellikle bir arabirim kullanırsınız.

interface KeyboardListener
{
    void KeyDown(int key);
    void KeyUp(int key)
    void KeyPress(int key);
    .... and so on
}

Bu, sınıfınızın tüm bu yöntemleri açıkça uygulamak zorunda kalacağı ve sadece uygulamak isteseniz bile hepsi için taslaklar sunacağı anlamına gelir KeyPress(int key).

C # 'da, bu olaylar c #' daki "event" anahtar kelimesi tarafından gizlenen, her tekil olay için bir tane olan delege listeleri olarak gösterilecektir. Bu, sınıfınızı genel "Anahtar" yöntemleri vb. İle zorlamadan istediğinize kolayca abone olabileceğiniz anlamına gelir.

3-5 puan için +1.

Bunlara ek olarak:

Delegeler, örneğin bir listeyi alan ve her öğeyi aynı miktarda öğeyle, ancak bir şekilde farklı olan yeni bir listeye yansıtan bir "harita" işlevi sağlamak istediğinizde çok kullanışlıdır. Temel olarak, IEnumerable.Select (...).

IEnumerable.Select, bir Func<TSource, TDest>TSource öğesini alan ve bu öğeyi bir TDest öğesine dönüştüren bir işlevi saran bir temsilci olan bir seçer.

Java'da bunun bir arayüz kullanılarak uygulanması gerekecektir. Böyle bir arayüzü uygulamak için genellikle doğal bir yer yoktur. Bir sınıf, bir şekilde dönüştürmek istediği bir liste içeriyorsa, "ListTransformer" arabirimini uygulaması çok doğal değildir, çünkü özellikle farklı şekillerde dönüştürülmesi gereken iki farklı liste olabilir.

Tabii ki, benzer bir kavram olan anonim sınıfları (java'da) kullanabilirsiniz.



@YamMarcovic Haklısın, doğrudan sorularını yanıtlamak yerine biraz serbest bırakıldım. Yine de, ilgili mekanik hakkında biraz açıklama yaptığını düşünüyorum. Ayrıca, soruyu cevapladığımda soruları biraz daha az şekilliydi. : p
Maksimum

Doğal olarak. Bana da olur ve kendi başına bir değeri vardır. Bu yüzden sadece önerdim , ama şikayet etmedim. :)
Yam Marcovic

3

1) Olay kalıpları, klasik olan Observer kalıbı, işte iyi bir Microsoft bağlantısı Microsoft talk Observer

Bağlandığınız makale çok iyi yazılmış değil imo ve işleri gereğinden daha karmaşık hale getiriyor. Statik iş sağduyuludur, statik üyelerle bir arayüz tanımlayamazsınız, bu yüzden statik bir yöntemde polimorfik davranışlar istiyorsanız bir temsilci kullanırsınız.

Yukarıdaki bağlantı, delegeler ve kompozisyon için neden iyi olduklarından bahsediyor, bu yüzden sorgunuza yardımcı olabilir.


3

Her şeyden önce iyi bir soru. "En iyi uygulamaları" körü körüne kabul etmek yerine, yardımcı programa odaklanmanıza hayranım. Bunun için +1.

Bu kılavuzu daha önce okudum. Bununla ilgili bir şeyleri hatırlamanız gerekiyor - bu sadece bir rehberdir, temel olarak programlamayı bilen fakat bir şeyleri yapmanın C # yöntemine aşina olmayan C # yeni başlayanlar için. Kuralların bir sayfası kadar değil, işlerin genellikle nasıl yapıldığını açıklayan bir sayfa olduğu kadar değildir. Zaten her yerde bu şekilde yaptıklarından, tutarlı kalmak iyi bir fikir olabilir.

Meseleye cevap vereceğim, sorularınızı cevaplayarak.

Öncelikle, bir arayüzün ne olduğunu zaten bildiğinizi varsayıyorum. Bir temsilci gelince, bir yönteme yazılan bir işaretçi, thiso yöntem için argümanı temsil eden nesneye isteğe bağlı bir işaretçi ile birlikte içeren bir yapı olduğunu söylemek yeterli . Statik yöntemlerde, son işaretçi boştur.
Aynı zamanda delegelere benzeyen, ancak bu yapıların birçoğuna atanan Çok Noktaya Yayınlı delegeler de vardır (çok noktaya yayın delegesine davet etmek için yapılan tek bir çağrı anlamına gelir, atanan çağrı listesindeki tüm yöntemleri çağırır).

Gelecekteki bir tasarım deseni ile ne demek istiyorlar?

C # 'daki olayların kullanılması anlamına gelir (bu son derece kullanışlı kalıbı karmaşık bir şekilde uygulamak için özel anahtar kelimeler vardır). C # olayları çok noktaya yayın delegeleri tarafından desteklenir.

Bu örnekte olduğu gibi bir etkinlik tanımladığınızda:

class MyClass {
  // Note: EventHandler is just a multicast delegate,
  // that returns void and accepts (object sender, EventArgs e)!
  public event EventHandler MyEvent;

  public void DoSomethingThatTriggersMyEvent() {
    // ... some code
    var handler = MyEvent;
    if (handler != null)
      handler(this, EventArgs.Empty);
    // ... some other code
  }
}

Derleyici aslında bunu aşağıdaki koda dönüştürür:

class MyClass {
  private EventHandler MyEvent = null;

  public void add_MyEvent(EventHandler value) {
    MyEvent += value;
  }

  public void remove_MyEvent(EventHandler value) {
    MyEvent -= value;
  }

  public void DoSomethingThatTriggersMyEvent() {
    // ... some code
    var handler = MyEvent;
    if (handler != null)
      handler(this, EventArgs.Empty);
    // ... some other code
  }
}

Daha sonra yaparak bir etkinliğe abone olursunuz.

MyClass instance = new MyClass();
instance.MyEvent += SomeMethodInMyClass;

Hangi aşağı derler

MyClass instance = new MyClass();
instance.add_MyEvent(new EventHandler(SomeMethodInMyClass));

Yani bu C # (ya da genel olarak .NET) içinde oluyor.

Bir temsilci kullanılırsa kompozisyonun kolay olduğu ortaya çıktı?

Bu kolayca gösterilebilir:

Kendisine iletilecek bir dizi eyleme bağlı bir sınıfınız olduğunu varsayalım. Bu eylemleri bir arayüze yerleştirebilirsiniz:

interface RequiredMethods {
  void DoX();
  int DoY();
};

Ve sınıfınıza eylemleri geçmek isteyen herkes ilk önce bu arayüzü uygulamak zorunda kalacaktı. Veya aşağıdaki sınıfa bağlı olarak hayatlarını kolaylaştırabilirsiniz :

sealed class RequiredMethods {
  public Action DoX;
  public Func<int> DoY();
}

Bu şekilde arayanlar sadece bir RequiredMethods örneği oluşturmak ve çalışma zamanında delegelere bağlama yöntemlerini kullanmak zorundadır. Bu ise genellikle daha kolaydır.

Bu tür şeyler yapmanın doğru koşullar altında son derece yararlıdır. Bir düşünün - neden tek umurunda olduğunuz bir uygulamanın size iletilmesiyken bir arayüze bağlısınız?

Bir grup ilgili yöntem olduğunda arayüz kullanmanın faydaları

Arayüzlerin kullanılması faydalıdır çünkü arayüzler normalde açık derleme zamanı uygulamaları gerektirir. Bu, yeni bir sınıf oluşturduğunuz anlamına gelir.
Tek bir pakette bir grup ilgili yönteminiz varsa, bu paketin kodun diğer bölümleri tarafından tekrar kullanılabilir olması yararlı olacaktır. Yani bir grup delegeyi oluşturmak yerine bir sınıfı başlatabilirlerse daha kolay olur.

Bir sınıf sadece bir uygulamaya ihtiyaç duyuyorsa arayüz kullanmanın faydaları

Daha önce belirtildiği gibi, arayüzler derleme zamanında uygulanmaktadır - bu, bir delegenin çağrılmasından daha verimli oldukları anlamına gelir (bu, kendi başına bir indirme seviyesidir).

"Bir uygulama", tek bir iyi tanımlanmış yerin bulunduğu bir uygulama anlamına gelebilir.
Aksi bir uygulama programında herhangi bir yerden gelebilir sadece olur yöntem imzası uygundur. Bu, daha fazla esneklik sağlar, çünkü yöntemlerin açıkça belirli bir arayüzü uygulayan bir sınıfa girmekten ziyade, yalnızca beklenen imzaya uyması gerekir. Ancak bu esnekliğin bir bedeli olabilir ve aslında Liskov Yer Değiştirme ilkesini ihlal eder , çünkü çoğu zaman açıklık istersiniz, çünkü kaza şansını en aza indirir. Tıpkı Statik Yazma gibi.

Bu terim ayrıca buradaki çok noktaya yayın delegelerine de atıfta bulunabilir. Arabirimler tarafından bildirilen yöntemler bir uygulama sınıfında sadece bir kez uygulanabilir. Ancak delegeler sırayla çağrılacak olan birden fazla yöntem biriktirebilirler.

Sonuç olarak, rehber yeterince bilgilendirici değil gibi görünüyor ve sadece olduğu gibi işliyor - bir rehber, bir kural defteri değil. Bazı tavsiyeler aslında biraz çelişkili görünebilir. Neyi uygulamanın doğru olup olmadığına karar vermek size bağlıdır. Kılavuz bize genel bir yol gösteriyor gibi görünüyor.

Umarım sorularınız memnuniyetinize cevaplanmıştır. Ve yine, soru için kudos.


2

.NET belleği hafızam hala duruyorsa, bir temsilci temelde bir ptr veya functor işlevidir. Bir fonksiyon çağrısına bir dolaylı katman ekler, böylece çağrılar kodunu değiştirmek zorunda kalmadan fonksiyonların yerini alabilir. Bu, bir arabirimin birden fazla işlevi bir arada paketlemesi dışında ve bir uygulayıcı bunları birlikte uygulamak zorunda olması dışında, aynı şeydir.

Genel olarak konuşursak, bir olay paterni başka bir yerdeki olaylara (Windows mesajları gibi) tepki veren bir kalıptır. Olaylar genellikle açık uçludur, herhangi bir sırayla gelebilir ve mutlaka birbirleriyle ilişkili değildir. Temsilciler bunun için iyi çalışırlar, çünkü her olay aynı zamanda çok sayıda alakasız fonksiyon içerebilecek bir dizi uygulama nesnesine ihtiyaç duymadan tek bir fonksiyonu arayabilir. Ayrıca (burası .NET belleğimin belirsiz olduğu yer), bir olaya birden fazla delegenin eklenebileceğini düşünüyorum.

Kompozisyon, terime çok aşina olmasam da, temelde, çalışmanın aktarıldığı alt bölümleri veya toplu çocukları olan bir nesneyi tasarlıyor. Delegeler, bir ara yüzün aşırı yüklenebileceği veya çok fazla eşleşmeye neden olabileceği ve bununla birlikte gelen sağlamlık ve kırılganlığa neden olabileceği yerlerde çocukların daha fazla geçici olarak karıştırılmasına ve eşleştirilmesine izin verir.

İlgili yöntemler için bir arayüzün faydası, yöntemlerin uygulayıcı nesnenin durumunu paylaşabilmesidir. Temsilci işlevleri, durumu net bir şekilde paylaşamaz ve hatta içeremez.

Bir sınıfın tek bir uygulamaya ihtiyacı varsa, bir arayüz bütün koleksiyonu uygulayan herhangi bir sınıf içinde, yalnızca bir uygulama yapılabilir ve bir uygulama sınıfının (eyalet, kapsülleme vb.) Faydalarını elde edersiniz, daha uygundur. Uygulama çalışma zamanı durumuna bağlı olarak değişebilirse, delegeler diğer yöntemleri etkilemeden diğer uygulamalar için değiştirilebileceklerinden daha iyi çalışırlar. Örneğin, her birinin iki olası uygulaması olan üç delege varsa, tüm olası devlet kombinasyonlarını hesaba katmak için üç yöntem arayüzünü uygulayan sekiz farklı sınıfa ihtiyacınız olacaktır.


1

"Olay" tasarım deseni (Gözlemci Şablonu olarak daha iyi bilinir), aynı imzanın birden çok yöntemini temsilciye eklemenizi sağlar. Bunu bir arayüzle gerçekten yapamazsınız.

Kompozisyonun bir temsilci için bir arayüzden daha kolay olduğuna hiç inanmıyorum. Bu çok garip bir ifade. Acaba anlamını yitirir, çünkü bir delegeye isimsiz yöntemler ekleyebilirsin.


1

Sunabileceğim en büyük açıklama:

  1. Bir temsilci bir işlev imzasını tanımlar; eşleşen bir işlevin hangi parametreleri kabul edeceğini ve ne döndüreceğini belirler.
  2. Bir arayüz, bir dizi fonksiyon, olay, özellik ve alan ile ilgilidir.

Yani:

  1. Bazı işlevleri aynı imzayla genelleştirmek istediğinizde bir temsilci kullanın.
  2. Bir sınıfın davranışını veya kalitesini genelleştirmek istediğinizde bir arayüz kullanın.

1

Olaylarla ilgili sorunuz çoktan ele alındı. Ayrıca bir arayüzün yapabileceği de doğrudur. birden çok yöntem define (ama aslında gerekmez) bir birey fonksiyonu üzerine bir işlev türü ise sadece hiç koyar kısıtlamalar.

Ancak asıl fark şudur:

  • Fonksiyon değerleri yapısal alt tipleme ile fonksiyon tiplerine uyarlanır (yani istenen yapıya örtük uyumluluk). Bu, bir işlev değerinin işlev türüyle uyumlu bir imzası varsa, tür için geçerli bir değer anlamına gelir.
  • Örnekler arayüzlerle nominal alt tipleme ile eşleştirilir (yani bir adın açık kullanımı). Bu, örneğin bir sınıfın üyesiyse, verilen arayüzü açıkça uygulayan, örnek arayüz için geçerli bir değerdir. Bununla birlikte, nesne sadece arayüzler tarafından talep edilen tüm üyelere sahipse ve tüm üyeler uyumlu imzalara sahipse, ancak arayüzü açıkça uygulamıyorsa, arayüz için geçerli bir değer değildir.

Tabii ama bu ne anlama geliyor?

Bu örneği ele alalım (C # numaram çok iyi olmadığından kod haXe'dedir):

class Collection<T> {
    /* a lot of code we don't care about now */
    public function filter(predicate:T->Bool):Collection<T> { 
         //build a new collection with all elements e, such that predicate(e) == true
    }
    public function remove(e:T):Bool {
         //removes an element from this collection, if contained and returns true, false otherwise
    }
}

Şimdi, filtre metodu, koleksiyonun kendisine verilen mantığa bağlı değilken, koleksiyonun iç organizasyonundan habersiz, sadece küçük bir mantık parçasına rahatça geçişi kolaylaştırır. Harika. Bir sorun dışında:
toplama gelmez mantık bağlıdır. Koleksiyon, kendiliğinden, işlevin geçtiği işlevin bir koşula karşı bir değeri test etmek ve testin başarısını döndürmek için tasarlandığı varsayımını yapar. Tüm işlevlerin değil, bir argüman olarak bir değer alan ve bir boole döndüren gerçekte yalnızca birer tahmin olduğunu unutmayın. Örneğin koleksiyonumuzun remove metodu böyle bir fonksiyondur.
Aradığımızı varsayalım c.filter(c.remove). Sonuç unsurları tüm koleksiyonu olurdu csüreckendisi boş olur. Bu talihsiz bir durum, çünkü doğal olarak ckendisinin değişmez olmasını beklerdik .

Örnek çok inşa edilmiştir. Ancak, asıl sorun, c.filterargüman olarak bazı fonksiyon değerlerini çağıran kodun, o argümanın uygun olup olmadığını bilmenin bir yolu olmadığıdır (yani değişmez olanı koruyacaktır). İşlev değerini yaratan kod, bir yordam olarak yorumlanacağını bilebilir veya bilmeyebilir.

Şimdi bazı şeyleri değiştirelim:

interface Predicate<T> {
    function test(value:T):Bool;
}
class Collection<T> {
    /* a lot of code we don't care about now */
    public function filter(predicate:Predicate<T>):Collection<T> { 
         //build a new collection with all elements e, such that predicate.test(e) == true
    }
    public function remove(e:T):Bool {
         //removes an element from this collection, if contained and returns true, false otherwise
    }
}

Ne değişti? Değişen şey şu ki, şimdi hangi değere sahip olursa olsun filter, açıkça bir öngörü olma sözleşmesini imzaladı. Tabii ki kötü niyetli veya son derece aptal programcılar, arayüzün yan etkisiz olmayan ve bu nedenle de öngörülemeyen uygulamaları geliştiriyorlar.
Ancak artık gerçekleşemeyecek olan şey, birisinin dış yapısı nedeniyle yanlışlıkla bir belirleyici olarak yorumlanan bir mantıksal veri / kod birimi bağlamasıdır.

Bu yüzden yukarıda söylenenleri birkaç kelimeyle yeniden ifade etmek için:

  • arayüzler , nominal tipleme kullanarak ve dolayısıyla açık ilişkiler kullanarak anlamına gelir.
  • delegeler yapısal tiplendirme kullanarak ve dolayısıyla örtülü ilişkiler kullanarak

Açık ilişkilerin avantajı, onlardan emin olmanızdır. Dezavantajı ise açıklık yükünün üstesinden gelmeleridir. Tersine, örtük ilişkilerin dezavantajı (bizim durumumuzda bir fonksiyonun imzası istenen imza ile eşleşiyor), bir şeyleri bu şekilde kullandığınızdan% 100 emin olamayacağınızdır. Bunun avantajı, tüm ek yük olmadan ilişkiler kurabilmenizdir. Bir şeyleri hızlı bir şekilde birlikte atabilirsiniz, çünkü onların yapısı buna izin verir. Kolay kompozisyonun anlamı budur.
Bu LEGO gibi biraz: Eğer yapabilirsiniz basitçe bir yıldız savaşları dış yapısı izin veriyorsa çünkü, bir LEGO korsan gemiye figürü LEGO takın. Şimdi bunun çok yanlış olduğunu hissedebilirsiniz ya da tam olarak istediğiniz şey olabilir. Kimse seni durduramayacak.


1
"Arabirimi açıkça uygular" ("nominal alt tip" altında), arabirim üyelerinin açık veya örtük olarak uygulanması ile aynı olmadığını belirtmekte fayda var. C # 'da sınıflar her zaman açıkça söylediğiniz gibi uyguladıkları arayüzleri bildirmelidir. Ancak arayüz üyeleri açıkça (ör. int IList.Count { get { ... } }) Veya örtük olarak ( public int Count { get { ... } }) uygulanabilir. Bu ayrım, bu tartışma ile ilgili değildir, ancak okuyucuların kafasını karıştırmamak için söz edilmeyi hak eder.
phoog

@ phoog: Evet, değişiklik için teşekkürler. İlki mümkün olduğunu bilmiyordum bile. Ancak evet, bir dilin arabirim uygulamasını gerçekte nasıl uyguladığı çok değişkendir. Örneğin Objective-C'de, eğer uygulanmadıysa, yalnızca bir uyarı verecektir.
back2dos

1
  1. Olay tasarım deseni yayınlama ve abone olma mekanizmasını içeren bir yapıya işaret eder. Etkinlikler bir kaynak tarafından yayınlanır, her abone yayınlanan öğenin bir kopyasını alır ve kendi eylemlerinden sorumludur. Bu gevşek bir şekilde birleştirilmiş bir mekanizmadır çünkü yayıncının abonelerin orada olduğunu bilmesi gerekmez. Abonelere sahip olmak tek başına zorunlu değildir (bu hiçbiri olmayabilir)
  2. Bir arayüz bir arayüze kıyasla kullanılırsa, kompozisyon "daha kolaydır". Arabirimler, bir sınıf örneğini, bir kompozisyon yapı örneğinin "işleyiciye sahip" göründüğü bir "işleyici türü" nesnesi olarak tanımlar; bu nedenle, örneğin bir temsilci kullanılarak örneğin görünümü daha az kısıtlanır ve daha esnek hale gelir.
  3. Aşağıdaki yorumdan gönderimimi iyileştirmem gerektiğini öğrendim, referans için buna bakın: http://bytes.com/topic/c-sharp/answers/252309-interface-vs-delegate

1
3. Delegeler neden daha fazla oyuncu seçimi gerektiriyorlar ve neden daha sıkı birleşme bir fayda sağlıyor? 4. Delegeleri kullanmak için olayları kullanmak zorunda değilsiniz ve delegelerde de bir yöntem tutmak gibi bir şey - dönüş türü ve argümanlarının türleri olduğunu biliyorsunuz. Ayrıca, arabirimde bildirilen bir yöntem neden hataları ele almayı bir temsilciye iliştirilmiş bir yöntemden daha kolay hale getirsin?
Yam Marcovic

Sadece bir delegenin spesifik olması durumunda haklısın. Bununla birlikte, olayın ele alınması durumunda (en azından benim referansımla ilgili olan), özel türler için kapsayıcı olarak davranmak için her zaman bir değeri güvenli bir şekilde test edebilmek yerine, bir tür olayı türetmek zorundasınız. Değerleri kullanmadan önce türünüzü açmak zorundasınız.
Carlo Kuip

Bir arabirimde tanımlanmış bir yöntemin hataları ele almayı kolaylaştıracağını düşündüğüm için, derleyicinin bu yöntemden atılan istisna türlerini kontrol edebiliyor olması. İkna edici kanıt olmadığını biliyorum ama belki tercih olarak belirtilmeli?
Carlo Kuip

1
İlk önce delegeler ve arayüzler hakkında konuşuyorduk, olaylar ve arayüzler değil. İkincisi, bir EventHandler temsilcisi üzerinde bir etkinlik tabanı oluşturmak yalnızca bir kongredir ve hiçbir şekilde zorunlu değildir. Fakat yine de, buradaki olaylar hakkında konuşmak bir nevi özlüyor. İkinci yorumun gelince - istisnalar C # ile kontrol edilmez. Java ile karıştırıyorsunuz (bu arada, delegelerin bile yok).
Yam Marcovic

Bu konuda önemli farklılıkları açıklayan bir konu bulundu: bytes.com/topic/c-sharp/answers/252309-interface-vs-delegate
Carlo Kuip
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.