Arabirimler diğer arabirimleri genişletirse (ve bunu yaparken miras yöntemleri)


13

Bu genel bir soru olmasına rağmen şu anda yaşadığım bir soruna özgüdür. Şu anda benim çözümümde belirtilen bir arayüz var

public interface IContextProvider
{
   IDataContext { get; set; }
   IAreaContext { get; set; }
}

Bu arayüz genellikle program boyunca kullanılır ve bu nedenle ihtiyacım olan nesnelere kolayca erişebilirim. Ancak programımın bir kısmının oldukça düşük bir düzeyinde IAreaContext kullanacak ve bazı işlemleri gerçekleştirecek başka bir sınıfa erişmem gerekiyor. Ben de bu yaratılışı yapmak için başka bir fabrika arayüzü oluşturdum:

public interface IEventContextFactory 
{
   IEventContext CreateEventContext(int eventId);
}

Ben uygular bir sınıf var IContextProvider ve Ninject kullanılarak enjekte edilir. Ben sorundur bu kullanmak gerekir alana o IEventContextFactory erişimi olan IContextProvider sadece ve kendisi bu yeni arayüzü gerekecektir başka sınıfını kullanır. IEventContextFactory bu uygulamayı düşük düzeyde somutlaştırmak istemiyorum ve yerine genelinde IEventContextFactory arabirimi ile çalışmak istiyorum . Bununla birlikte, sadece ihtiyaç duyan sınıfa geçmesi için yapıcılar aracılığıyla başka bir parametre enjekte etmek istemiyorum.

// example of problem
public class MyClass
{
    public MyClass(IContextProvider context, IEventContextFactory event)
    {
       _context = context;
       _event = event;
    }

    public void DoSomething() 
    {
       // the only place _event is used in the class is to pass it through
       var myClass = new MyChildClass(_event);
       myClass.PerformCalculation();      
    }
}

Yani asıl sorum şu, bu kabul edilebilir mi, ya da böyle bir şey yapmak yaygın ya da iyi bir uygulama mı (arayüz başka bir arayüzü genişletir):

public interface IContextProvider : IEventContextFactory

veya ihtiyacım olanı başarmak için daha iyi alternatifler düşünmeli miyim? Eğer öneride bulunmak için yeterli bilgi vermediysem bana bildirin ve daha fazlasını sağlayabilirim.


2
Hiçbir arayüz aslında hiçbir şey uygulamadığı için soru başlığınızı "Arayüzler arayüzleri miras almalı" şeklinde yeniden yazardım.
Jesse C. Slicer

2
Genel dil, bir arabirimin üst öğesini "genişlettiği" ve (bunu yaparak) üst arabirimin yöntemlerini "devraldığı", bu nedenle burada "genişlet" seçeneğini kullanmanızı öneririm.
Theodore Murdock

Arayüzler ebeveynleri uzatabilir, neden kötü bir uygulama olsun ki? Bir arayüz meşru olarak başka bir arayüzün süper setiyse, elbette genişletmelidir.
Robin Winslow

Yanıtlar:


10

Arabirimler yalnızca herhangi bir uygulama olmadan davranışı tanımlasa da, kalıtım hiyerarşilerine katılabilirler. Örnek olarak, ortak bir fikriniz olduğunu varsayalım Collection. Bu arabirim, üyeler üzerinde yineleme yöntemi gibi tüm koleksiyonlar için ortak olan birkaç şey sağlar. Daha sonra a Listveya a gibi daha belirli nesne koleksiyonları hakkında düşünebilirsiniz Set. Bunların her biri, a'nın tüm davranış gereksinimlerini devralır Collection, ancak söz konusu koleksiyon türüne özgü ek gereksinimler ekler.

Arayüzler için kalıtım hiyerarşisi oluşturmak ne zaman mantıklıysa, o zaman yapmalısınız. İki arabirim her zaman birlikte bulunacaksa, büyük olasılıkla birleştirilmeleri gerekir.


6

Evet, ama sadece mantıklıysa. Kendinize aşağıdaki soruları sorun ve bir veya daha fazlası geçerliyse bir arabirimi diğerinden devralmak kabul edilebilir.

  1. Arayüz mu mantıksal olarak genişletir B arayüzü, örneğin IList ICollection'a işlevsellik ekleme.
  2. Arabirim Önceden başka bir arabirim tarafından belirtilen davranışın tanımlanması gerekir; örneğin, düzeltilmesi gereken kaynaklara sahipse IDisposable uygulanması veya yinelenebilirse IEnumerable.
  3. Her arabirim A uygulaması, arabirim B tarafından belirtilen davranışı gerektirir mi?

Örneğinizde, bunların hiçbirine evet yanıtı verdiğini sanmıyorum. Başka bir mülk olarak eklemeniz daha iyi olabilir:

public interface IContextProvider
{
   IDataContext DataContext { get; set; }
   IAreaContext AreaContext { get; set; }
   IEventContextFactory EventContextFactory { get; set; }
}

Nasıl bir özellik yapmak arayüzü genişletmek daha iyi olurdu, ya da konuşmak için kedi derisi için başka bir yol mudur?
dreza

1
Fark, eğer IContextProvidergenişletirseniz IEventContextFactory, ContextProvideruygulamanın bu yöntemi de uygulaması gerekecektir. Eğer bir mülk olarak ekleyin, bir söylüyoruz ContextProviderbir vardır IEventContextFactoryama aslında uygulama ayrıntılarını bilmiyor.
Trevor Pilley

4

Evet, bir arayüzü diğerinden uzatmak iyidir.

Belirli bir durumda yapılacak doğru şeyin olup olmadığı sorusu, ikisi arasında gerçek bir “is-a” ilişkisi olup olmadığına bağlıdır.

Geçerli bir "is-a" ilişkisi için ne gerekir?

İlk olarak, iki arabirim arasında gerçek bir fark olmalıdır, yani alt arabirimi uygulayan ancak alt arabirimi uygulayan durumlar olmalıdır. Her iki arabirimi uygulamayan örnekler yoksa ve asla olmayacaksa, bunun yerine iki arabirimin birleştirilmesi gerekir.

İkinci olarak, alt arabirimin her örneğinin mutlaka üst öğenin bir örneği olması gerekir: Alt arabirimin bir örneği olarak anlamlı olmayacak bir alt arabirim örneği oluşturacağınız (makul) bir mantık yoktur. Üst arabirim.

Eğer her ikisi de doğruysa, kalıtım iki arayüz için doğru ilişkidir.


Ben sadece türetilmiş değil, sadece temel arayüzü kullanan sınıflara sahip olmak gerekli olmadığını düşünüyorum. Örneğin, IReadOnlyListtüm liste sınıflarım uygulanıyor olsa bile IList(ki bu türetilmiştir IReadOnlyList) arayüz yararlı olabilir .
svick

1

Bir arabirim her zaman diğerini istemek / sağlamak istiyorsa, devam edin. Bunu birkaç durumda gördüm IDisposible. Bununla birlikte, genel olarak, arayüzlerden en az birinin sorumluluktan ziyade bir özellik gibi davrandığından emin olmalısınız.

Örneğin, net değil. Eğer ikisi de hep birlikteyse, sadece bir arayüz yapın. Eğer biri her zaman diğerine ihtiyaç duyarsa, çoğu zaman birden fazla sorumluluğa ve / veya diğer sızdıran soyutlama sorunlarına yol açan "X ve 1" türden bir mirastan endişe duyarım.


Bunun için teşekkürler. Sorumluluktan ziyade bir özellik gibi davranmakla ne demek istiyorsun?
dreza

@dreza SOLID'deki SRP'deki sorumluluk ve Scala özellikleri gibi bir özellik demek istiyorum. Çoğunlukla arayüzün probleminizi nasıl modellediği kavramı . Problemin birincil bölümünü mi yoksa başka türlü farklı türlerin ortak bir parçasını mı temsil ediyor?
Telastyn
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.