在接口中声明成员函数

时间:2013-01-24 21:24:04

标签: c# interface member

首先,我对C#很陌生。我想有一个接口声明一个成员函数,如下面的代码片段

interface IMyInterface {
    void MyAction() {
        // do stuff depending on the output of function()
    }
    void Function();
}

此处Function是纯虚拟的,应由IMyInterface的孩子实施。我可以使用抽象类而不是接口,但后来我无法从其他类继承...例如,MyAction递归搜索目录中的文件并将Function应用于任何找到的文件让我的榜样清楚。

如何更改我的设计以克服接口无法实现类的约束?

编辑:在C ++中我要做的就是使用模板

template<class A>
static void MyAction(const A& a) {
    // do stuff depending on the output of A::Function()
};

class MyClass {
    void Function();
};

我想知道是否有一种优雅的方法可以使用C#中的接口来实现这一点。

9 个答案:

答案 0 :(得分:11)

直接处理这个问题的唯一方法是使用抽象类,因为接口不能包含任何形式的“逻辑”,而只是一个契约。

然而,一种替代方案是创建接口和静态类。然后,您可以使用界面将逻辑放在扩展方法中。

public interface IMyInterface {
    void Function();
}

public static class MyInterfaceExtensions {
    public static void MyAction(this IMyInterface object)
    {
       // use object.Function() as needed
    }
}

这里的主要缺点是更多类型,这降低了可维护性,并且缺乏可发现性。

答案 1 :(得分:10)

在C#中,您没有多重继承。您可以使用合成来规避此限制。

像这样定义你的界面(这里不需要定义Function):

public interface IMyInterface
{
    void MyAction();
}

使用抽象Function声明一个抽象类并实现此接口:

public abstract class MyInterfaceBase : IMyInterface
{
    public void MyAction()
    {
        // Do stuff depending on the output of Function().
        Function();
    }

    protected abstract void Function();
}

从这个抽象类中,您可以派生出具体的实现。这还不是你的“最终”类,但它将被用来组成它。

public class ConcreteMyInterface : MyInterfaceBase
{
    protected override void Function()
    {
        Console.WriteLine("hello");
    }
}

现在让我们来到你的“最后”,写作课。它将源自SomeBaseClass并通过集成IMyInterface的功能来实现ConcreteMyInterface

public class SomeBaseClass
{
}

public class MyComposedClass : SomeBaseClass, IMyInterface
{
    private readonly IMyInterface _myInterface = new ConcreteMyInterface();

    public void MyAction()
    {
        _myInterface.MyAction();
    }
}

<强>更新

在C#中,您可以声明本地类。这更接近于多重继承,因为您可以在编写类中派生所有内容。

public class MyComposedClass : SomeBaseClass, IMyInterface
{
    private readonly IMyInterface _myInterface = new ConcreteMyInterface();

    public void MyAction()
    {
        _myInterface.MyAction();
    }

    private class ConcreteMyInterface : MyInterfaceBase
    {
        protected override void Function()
        {
            Console.WriteLine("hello");
        }
    }
}

答案 2 :(得分:7)

您可以将MyAction定义为extension method

public interface IMyInterface
{
   void Function();
}

public static class MyInterfaceExtensions
{
    public static void MyAction(this IMyInterface obj)
    {
        obj.Function();
    }
}

示例:

public class HelloWorld : IMyInterface
{
    public void Function()
    {
        Console.WriteLine("Hello World");
    }

    public static void Main(string[] args)
    {
        new HelloWorld().MyAction();
    }
} 

输出:

Hello World

答案 3 :(得分:2)

接口无法实现任何只是合同的行为。如果要在定义合同时实现某些逻辑,可以使用抽象类。

答案 4 :(得分:2)

为此目的。你需要定义抽象类。 您可以提供默认实现,也可以将实现留给派生类。

如果派生类想要覆盖某些东西,他们总是可以这样做。 这使他们可以灵活地使用base以及他们想要覆盖的更改。

答案 5 :(得分:1)

在界面中声明函数的接口(签名和返回类型), 然后创建一个定义为实现该接口的抽象类,并在抽象类中实现基本的默认实现。然后,创建从抽象类继承的其他具体类,但在必要时,使用不同的实现覆盖抽象类基本实现。

答案 6 :(得分:1)

通过分离外部行为可以最好地克服这类问题;在这种情况下,MyAction来自内部实施; MyFunction

这里的要点是理解该类与其他类之间的接口/契约应该是什么,以及应该成为该合同实现的一部分。

此处,定义了此对象与其使用者之间的契约;

interface IMyInterface
{
    void MyAction();
}

现在,实现此接口的基类,并强制执行特定行为;

abstract class BaseClass : IMyInterface
{
    public void MyAction()
    {
        // do some commmon action

        // call derived implementation to deal with the outcome
    }

    protected abstract MyFunvoid ction();
}

最后,以具体方式处理MyFunction结果的具体实现;

class ConcreteClass : BaseClass
{
    protected override void MyFunction()
    {
         // concrete iomplementation here
    }
}

答案 7 :(得分:0)

接口是契约,不能包含实现。

从您上面的陈述中:

  

我可以使用抽象类而不是接口但是我无法继承其他类

我相信你会遇到“为什么C#不支持多重继承”的问题。

以下是Simulated Multiple Inheritance for C#上的CodeProject文章。您应该能够遵循此模式来实现C#的简单继承模型的变通方法。

答案 8 :(得分:0)

这是C#8.0的建议功能:

interface IA
{
    void M() { WriteLine("IA.M"); }
}

class C : IA { } // OK

IA i = new C();
i.M(); // prints "IA.M"`

https://github.com/dotnet/csharplang/blob/master/proposals/default-interface-methods.md