2012-01-18 114 views
7

我有一个C#接口和一个实现该接口的具体类。我现在想创建另一个实现该接口的类。够简单。C#接口和基类

但是,大多数方法在类中完全一样,只有几个方法会实际改变。

我不想复制我的第一个类中包含的所有逻辑。

如何创建第二类,并使用我的第一课中的逻辑,除了额外的东西?

我的接口被称为IEventRepository,我的第一个类被称为BaseEvents。我现在想创建一个名为FooBarEvents的新类。

我给FooBarEvents类定义是:

public class FooBarEvents : BaseEvents, IEventRepository 

我的目的是,然后使用在每个复制方法的代码的返回base.Method()。

我假设这是不正确的?

+0

准确地说,你为什么要使用接口? – 2012-01-18 15:54:23

回答

10

FooBarEvents应该只需要从BaseEvents继承,不是也实现IEventRepository,为BaseEvents已经实现了接口。如果您需要更改FooBarEvents中某些IEventRepository方法的行为,请仅覆盖这些方法。

编辑:一些例子

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

我得到这个,但FooBarEvents类将是客户特定的,并且可能有另外10个方法未在BaseEvents中实现(它们是特定的)。 BaseEvents有10个方法都是虚拟的,什么也不做,只是抛出一个未实现的异常或无效的操作异常,这不是不好的做法吗? – Paul 2012-01-18 16:05:20

+0

我不知道我明白你在问什么。你是说你会为'FooBarEvents'添加10个客户端特定的方法,但是你必须将这些事件的签名添加到'BaseEvents'中才能覆盖它们?事实并非如此;你可以直接将实现添加到'FooBarEvents'中。我会编辑我的答案并添加一个例子。 – 2012-01-18 16:10:03

+0

如果我没有将这些签名添加到BaseEvents,那么我会得到一个错误,说BaseEvents没有实现某些接口成员。我正在使用依赖注入,所以我需要在我的FooBarEvents类中将合约添加到我想要的成员的接口中。 – Paul 2012-01-18 16:18:04

6

由于BaseEvents已经实现了IEventRepository,所以您不需要在FooBarEvents中再次实现它。 FooBarEvents自动继承BaseEvents'的实现。

2

你可以让你的第二课延长你的第一堂课。你的第一个类可以是抽象的,但只能实现接口中的常用方法。

+0

“你可以让你的第二堂课扩展到第二堂课” - 你的意思是“延长你的第一堂课”? – 2012-01-18 15:56:35

+0

对不起 - 你是对的samuel – 2012-01-18 15:58:37

+0

我正在使用Ninject依赖注入,它不想知道抽象类。 – Paul 2012-01-18 16:13:09

0

如果在BaseEvents实施IEventRepository方法有一定的选择是总是要保持相同的实现,那么你可以实现他们在BaseEvents类和标记可能更改为virtual。这样,如果FooBarEvents希望更改其中一种方法的实现,则它可以简单地覆盖它。

只需将IEventsRepository添加到您的FooBarEvents类中即可:请务必这样做。关于它的Jon Skeet回答见here

3

为什么你不在基类中定义你的方法为Virtual覆盖你想在子类中改变的方法?

2

使用继承:

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() {...} 
} 

BarOnSteroids将继承Bar所有的所作所为,就可以改变的,你需要在BarOnSteroids覆盖它们(他们需要被标记为基类中的虚拟的任何方法的具体行为Bar)。

这种方式,您将有以下:

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. 

这是假设你想改变的是对IFoo接口的一部分方法的具体行为。如果您只想添加其他功能到BarOnSteroids,那么只需继承Bar即可继承其所有功能并添加所有必需的新方法来实现新功能。

+0

因此,如果我正在使用Bar使用IFoo并调用SpecificBehaviourMethod1,我想我会得到一个NotImplementedException,好像BarOnSteroids做了一些Bar不是? – Paul 2012-01-18 15:59:55

+0

@Pual。请参阅edit for answer。简而言之,'Bar'和'BarOnSteroids'必须实现'SpecificBehaviorMethod1',因为这个方法是'IFoo'合约的一部分,在'SpecificBehaviorMethod'是虚拟的情况下,它会调用特定于你正在调用的实例的实际类型的实现 – InBetween 2012-01-18 16:10:19

3

以下代码显示了如何使用抽象基类提供某些接口方法的通用实现,并为其他接口提供了自定义实现。

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

我们可以有一个显式接口实现声明在这种情况下?我的意思是像IEventRepository.Method2(){}。 – remio 2012-01-18 16:08:04

+0

当然,但我并不真正理解显式接口的价值 – Jason 2012-01-18 16:11:21

+0

在我看来,它通过帮助客户端类忘记底层实现来强制执行类型。 – remio 2012-01-19 17:50:00

0

有几个不同的方法。

一。完全跳过界面,并将其变为抽象类。这是简单的,当它的工作原理,但事实上,你只能有一个基类,限制在C#中使用

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 
    } 
} 

你可以有一个类实现接口,并从它的另一个派生:

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; 
    } 
} 

他们还可以使用具有无关的层次结构中的静态辅助类,但确实提供了在实现功能时很有用的方法。

警惕虽然这种模式的:

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 

即使IEventRepository.Method1定义更明智地,上述是可能导致混乱。