2012-01-18 26 views
7

C# arabirim var ve bu arabirimi uygulayan somut bir sınıf var. Şimdi bu arayüzü uygulayan başka bir sınıf oluşturmak istiyorum. Yeterince basit. Bununla birlikte, çoğu yöntem sınıflarda tam olarak aynı olacaktır ve yalnızca birkaç yöntem değişecektir.C# Arabirim ve temel sınıflar

İlk mantığımdaki tüm mantığı çoğaltmak istemiyorum.

2. sınıfı nasıl oluşturabilirim ve birinci sınıfımdaki mantığı ekstra öğeler dışında nasıl kullanırım?

Arabirim IEventRepository olarak adlandırılıyor ve 1. sınıfıma BaseEvents denir. Şimdi FooBarEvents adında yeni bir sınıf oluşturmak istiyorum. FooBarEvents için

Sınıfım tanımı:

public class FooBarEvents : BaseEvents, IEventRepository 

amacım daha sonra kodu çoğaltan her yöntemde dönüş base.Method() kullanmaktı.

Bunun doğru olmadığını mı varsayıyorum?

+0

Tam olarak neden bir arabirim kullanıyorsunuz? –

cevap

10

FooBarEvents sadece BaseEvents zaten arabirimini uygulayan olarak değil, aynı zamanda, IEventRepository uygulamak, BaseEvents devralmak gerekir gerekir. Bazı IEventRepository yöntemlerinin davranışını FooBarEvents içinde değiştirmeniz gerekirse, bu yöntemleri geçersiz kılmanız yeterlidir.

Düzenleme: IEventRepository arasında BaseEvents uygulanmasında yöntemlerin belli seçim daimao zaman sadece BaseEvents sınıf ve işareti bunları uygulayabilir, aynı uygulamayı sürdürmek olacak ise bazı örnekler

interface IEventRepository 
{ 
    void CommonMethodA(); 
    void CommonMethodB(); 
    void ImplentationSpecificMethod(); 
} 

abstract class BaseEvents : IEventRepository 
{ 
    public void CommonMethodA() 
    { ... } 

    public virtual void CommonMethodB() 
    { ... } 

    public abstract void ImplementationSpecificMethod(); 

    public void BaseEventsMethod() 
    { ... } 

    public void BaseEventsMethod2() 
    { ... } 
} 

class FooBarEvents : BaseEvents 
{ 
    public override void CommonMethodB() 
    { 
     // now FooBarEvents has a different implementation of this method than BaseEvents 
    } 

    public override void ImplementationSpecificMethod() 
    { 
     // this must be implemented 
    } 

    public new void BaseEventsMethod2() 
    { 
     // this hides the implementation that BaseEvents uses 
    } 

    public void FooBarEventsMethod() 
    { 
     // no overriding necessary 
    } 
} 

// all valid calls, assuming myFooBarEvents is instantiated correctly 
myFooBarEvents.CommonMethodA() 
myFooBarEvents.CommonMethodB() 
myFooBarEvents.BaseEventsMethod(); 
myFooBarEvents.BaseEventsMethod2(); 
myFooBarEvents.FooBarEventsMethod(); 
myFooBarEvents.ImplementationSpecificMethod(); 

// use the contract thusly: 
void DoSomethingWithAnEventRepository(BaseEvents events) 
{ ... } 
+0

Bunu anlıyorum, ancak FooBarEvents sınıfı istemciye özgü olacak ve BaseEvents uygulamasında uygulanmayan başka 10 yönteme sahip olabilir (bunlar belirlidir). BaseEvents'lar için 10 yöntemin sanal olarak ve hiçbir şey yapmadan ancak uygulanan istisna veya geçersiz operasyon istisnasını atmak kötü bir uygulama olmaz mı? – Paul

+0

Sorduğun şeyi anladığımdan emin değilim.FooBarEvents'a 10 müşteriye özel yöntem ekleyeceğinizi mi söylüyorsunuz, ancak bu etkinlikleri geçersiz kılmak için bu olayların imzalarını 'BaseEvents' olarak eklemelisiniz? Konu bu değil; uygulamaları doğrudan 'FooBarEvents' öğesine ekleyebilirsiniz. Cevabımı düzenleyip bir örnek ekleyeceğim. –

+0

Bu imzaları BaseEvents'a eklemezsem, BaseEvent'lerin belirli arabirim üyelerini uygulamadığını söyleyen bir hata alırız. Bağımlılık enjeksiyonunu kullanıyorum, bu yüzden sözleşmeyi FooBarEvents sınıfımda istediğim üyeler için arayüze eklemem gerekecek. – Paul

6

BaseEvents zaten IEventRepository uygular, FooBarEvents içinde yeniden uygulamanız gerekmez. FooBarEvents, otomatik olarak BaseEvents 'uygulamasını devralır.

2

İkinci sınıfınızı birinci sınıfınızı genişletebilirsiniz. Birinci sınıfınız soyut olabilir, ancak sadece ortak yöntemleri arayüzden uygular.

+0

"İkinci sınıfınızı ikinci sınıfınızı genişletebilirsiniz" - "birinci sınıfınızı uzatmak" anlamına mı geliyor? –

+0

yes sorry - do you right samuel –

+0

Soyut sınıflar hakkında bilmek istemeyen Ninject bağımlılık enjeksiyonunu kullanıyorum. – Paul

0

'un virtual olarak değiştirilebileceği durumlar. Bu şekilde, FooBarEvents, yöntemlerden birinin uygulanmasını değiştirmek isterse, bunu geçersiz kılabilir.

IEventsRepository ürününün FooBarEvents sınıfına eklenmesiyle ilgili bir not: Bunu yapmak geçerli. Bir Jon Skeet cevabı için here'a bakın.

3

Yöntemlerinizi neden temel sınıfta Virtual ve alt sınıflarını alt sınıfta değiştirmek istediğinizi tanımlamıyorsunuz?

2

Kullanım miras:

public interface IFoo 
{ 
    void GeneralBehaviorMethod1(); 
    void GeneralBehaviorMethod2(); 
    void SpecificBehaviorMethod1(); 
} 

public class Bar: IFoo 
{ 
    public void GeneralBehaviorMethod1() {...} 
    public void GeneralBehaviorMethod2() {...} 

    public virtual void SpecificBehaviorMethod1() {...} 
    ... 
} 

public class BarOnSteroids: Bar 
{ 
    public override void SpecificBehaviorMethod1() {...} 
} 

BarOnSteroidsBar tüm davranışlarını devralır ve size (onlar temel sınıf sanal olarak işaretlenmesi gerekir BarOnSteroids bunları geçersiz kılarak gereken herhangi yöntemlerin spesifik davranışını değiştirebilir Bar). Aşağıdaki olurdu

Bu şekilde:

IFoo iFoo = new Bar(); 
iFoo.SpecificBehaviorMethod1(); //Bar implementation will be called; 

IFoo iFoo = new BarOnSteroids(); 
iFoo.SpecificBehaviorMethod1(); //BarOnSteroids implementation will be called. 
iFoo.CommonBehaviorMethod1(); //Bar implementation will be called. 

Bar bar = new BarOnSteroids(); 
bar.SpecificBehaviorMethod1(); //BarOnSteroids implementation will be called. 
bar.CommonBehaviorMethod1(); //Bar implementation will be called. 

Bu IFoo arabiriminin parçası olan yöntemlerin belirli davranışlarını değiştirmek istiyorum varsayar. Tek yapmanız gereken, BarOnSteroids'a ek işlevsellik eklemekse, tüm işlevselliğini devralmak ve yeni işlevselliği uygulamak için gerekli tüm yeni yöntemleri eklemek için Bar formunu miras almanız yeterlidir.

+0

Eğer Bar kullanarak IFoo Tüketiyordum ve SpecificBehaviourMethod1 deniyorsa sanırım bir NotImplementedException sanki BarOnSteroids bir şey yapmaz sanki Bar doesnt? – Paul

+0

@Pual.Son Hayır, hem de "Bar" hem de "BarOnSteroids" 'SpecificBehaviorMethod1' uygulamalısınız, çünkü bu yöntem 'IFoo' sözleşmesinin bir parçasıdır.' SpecificBehaviorMethod 'ifadesinin sanal olması durumunda, arayacağınız örneğin gerçek türüne özgü uygulamayı çağırır. – InBetween

3

Aşağıdaki kod soyut temel sınıf ile bazı arayüz yöntemlerinin ortak uygulanmasını sağlamak, ve diğerleri için özel uygulamaları sağlamak için nasıl gösterir.

public interface IEventRepository 
{ 
    void Method1(); 
    void Method2(); 
} 

public abstract class BaseEvents : IEventRepository 
{ 
    public void Method1() 
    { 
    Console.WriteLine("This is shared functionality"); 
    } 

    public abstract void Method2(); 
} 

public class Implementation1 : BaseEvents 
{ 
    override public void Method2() 
    { 
    Console.WriteLine("Impl1.Method2"); 
    } 
} 

public class Implementation2 : BaseEvents 
{ 
    override public void Method2() 
    { 
    Console.WriteLine("Impl2.Method2"); 
    } 
} 

public class Program 
{ 
    static void Main(string[] args) 
    { 
    var implementations = new List<IEventRepository> { new Implementation1(), new Implementation2() }; 

    foreach (var i in implementations) 
    { 
     Console.WriteLine(i.GetType().Name); 
     Console.Write("\t"); 
     i.Method1(); // writes 'This is shared functionality' 

     Console.Write("\t"); 
     i.Method2(); // writes type specific message 
    } 
    } 

}

+0

Bu durumda açık arabirim uygulama bildirimi? IEventRepository.Method2() {} . – remio

+0

emin gibi bir şey demek, ama ben Açık arabirimlerin değerini anlamıyorum – Jason

+0

Benim bakış açımla, müşteri sınıfının temeldeki uygulamayı unutmasına yardımcı olarak türü zorlar. – remio

0

bazı farklı yaklaşımlar var.

One. Arayüzü tamamen atla ve soyut bir sınıf yap. çalıştığını, ancak yalnızca bir temel sınıfa sahip olabileceği gerçeği

public abstract class EventRepository 
{ 
    public abstract int MustBeOverridden(string str);//classes have to override this 
    public virtual int CanBeOverridden(int i)//classes can override but may choose not to. 
    { 
    return 4; 
    } 
    public int CannotOverride(string str)//this is always the same 
    { 
    return MustBeOverridden(str) + 3;//can make use of this 
    } 
} 

tek bir sınıf arabirimini uygulamak olabilir C# kullanımını kısıtlar, bu basittir ve başka ondan türetmek:

public interface IEventRepository 
{ 
    int Method1(string str); 
    int Method2(string str); 
} 

public class EventClass1 : IEventRepository 
{ 
    public int Method1(string str)//can't be overridden as not marked virtual 
    { 
    return 1; 
    } 
    public virtual int Method2(string str)//can be overridden 
    { 
    return 2; 
    } 
} 

public class EventClass2 : EventClass1 
{ 
    public override int Method2(string str) 
    { 
    return -2; 
    } 
} 

public abstract class EventClass : IEventRepository 
{ 
    public abstract int Method1(string str); 
    public int Method2(string str) 
    { 
    return 2; 
    } 
} 

public class EventClass1 : EventClass 
{ 
    public override int Method1(string str) 
    { 
    return 1; 
    } 
} 
public class EventClass2 : EventClass 
{ 
    public override int Method1(string str) 
    { 
    return -1; 
    } 
} 

Ayrıca, hiyerarşi ile ilgisi yoktur statik yardımcı sınıf kullanabilir fakat:

ikisini bazı ortak davranışlar veren soyut bir sınıf geçersiz kılmak mı işlevselliği uygulamada yararlı olan yöntemleri sağlar.

olsa bu desen karşı dikkatli olun: IEventRepository.Method1 daha makul tanımlandığında
public class EventClass1 : IEventRepository 
{ 
    public int Method1(string str)//not override-able 
    { 
    return 1; 
    } 
    public int Method2(string str)//not override-able 
    { 
    return 2; 
    } 
} 
public class EventClass2 : EventClass1, IEventRepository 
{ 
    //We really want our own Method1! 
    public new int Method1(string str) 
    { 
    return 3; 
    } 
    int IEventRepository.Method1(string str) 
    { 
    return -1; 
    } 
} 

EventClass2 e2 = new EventClass2(); 
EventClass1 e1 = e2; 
IEventRepository ie = e2; 
Console.WriteLine(e2.Method1(null));//3 
Console.WriteLine(e1.Method1(null));//1 
Console.WriteLine(ie.Method1(null));//-1 

bile, yukarıda karışıklığa yol açması muhtemeldir.

İlgili konular