C#接口的方法的默认实现?

时间:2015-05-19 09:42:18

标签: c# oop interface

是否可以在C#中定义具有默认实现的接口? (这样我们就可以定义一个实现该接口的类,而无需实现特定的默认方法)。

我知道扩展方法(例如this link中所述)。但这是我的答案,因为有一个类似下面的方法扩展,编译器仍抱怨在MyClass中实现MyMethod:

public interface IMyInterface
{
    string MyMethod();
}

public static class IMyInterfaceExtens
{
    public static string MyMethod(this IMyInterface someObj)
    {
        return "Default method!";
    }
}

public class MyClass: IMyInterface
{
// I want to have a default implementation of "MyMethod" 
// so that I can skip implementing it here
}

我问这个是因为(至少据我所知),可以用Java做到这一点(见here)。

PS:使用某种方法拥有抽象基类我的答案仅仅因为我们在C#中没有多重继承而且它与有接口的默认实现(如果可能!)。

6 个答案:

答案 0 :(得分:27)

我开发游戏所以我经常希望为接口的所有实现提供通用功能,但同时允许每个实现也做自己的事情,就像子类的'virtual / override方法一样。

我就是这样做的:

public class Example
{
    void Start()
    {
        WallE wallE = new WallE();
        Robocop robocop = new Robocop();

        // Calling Move() (from IRobotHelper)
        // First it will execute the shared functionality, as specified in IRobotHelper
        // Then it will execute any implementation-specific functionality,
        // depending on which class called it. In this case, WallE's OnMove().
        wallE.Move(1);

        // Now if we call the same Move function on a different implementation of IRobot
        // It will again begin by executing the shared functionality, as specified in IRobotHlper's Move function
        // And then it will proceed to executing Robocop's OnMove(), for Robocop-specific functionality.
        robocop.Move(1);

        // The whole concept is similar to inheritence, but for interfaces.
        // This structure offers an - admittedly dirty - way of having some of the benefits of a multiple inheritence scheme in C#, using interfaces.
    }

}

public interface IRobot
{
    // Fields
    float speed { get; }
    float position { get; set; }

    // Implementation specific functions.
    // Similar to an override function.
    void OnMove(float direction);
}

public static class IRobotHelper
{
    // Common code for all IRobot implementations. 
    // Similar to the body of a virtual function, only it always gets called.
    public static void Move(this IRobot iRobot, float direction)
    {
        // All robots move based on their speed.
        iRobot.position += iRobot.speed * direction;

        // Call the ImplementationSpecific function
        iRobot.OnMove(direction);
    }
}

// Pro-Guns robot.
public class Robocop : IRobot
{
    public float position { get; set; }

    public float speed { get; set;}

    private void Shoot(float direction) { }

    // Robocop also shoots when he moves
    public void OnMove(float direction)
    {
        Shoot(direction);
    }
}

// Hippie robot.
public class WallE : IRobot
{
    public float position { get; set; }

    public float speed { get; set; }

    // Wall-E is happy just moving around
    public void OnMove(float direction) { }
}

答案 1 :(得分:25)

C#v8将开始允许在接口中实现具体方法。这将使您的具体实现类在您将来更改正在实现的接口时不会中断。

所以下一个语言版本可以这样:

interface IA
{
    void NotImplementedMethod();
    void M() { WriteLine("IA.M"); } //method definition present in the interface
}

请参阅此GitHub issue # 288。此外,Mads Torgersen在this频道9视频中详细讨论了这一即将推出的功能。

注意:在撰写此答案时,RTM状态下C#语言的当前版本为v7。

答案 2 :(得分:15)

简答:

不,你不能在接口中编写方法的实现。

说明

接口就像契约一样,所以从它继承的类型必须定义实现,如果你有一个场景,你需要一个默认实现的方法,那么你可以创建你的类abstract并定义您想要的方法的默认实现。

例如:

public abstract class MyType
{
    public string MyMethod()
    {
      // some implementation
    }

    public abstract string SomeMethodWhichDerivedTypeWillImplement();
}

现在在Dervied班:

public class DerivedType : MyType
{
  // now use the default implemented method here
}

更新(C#8将支持此功能):

C# 8 will allow to have default implementation in interfaces

答案 3 :(得分:5)

不是直接的,但您可以为接口定义扩展方法,然后像这样实现它

public interface ITestUser
{
    int id { get; set; }
    string firstName { get; set; }
    string lastName { get; set; }

    string FormattedName();
}

static class ITestUserHelpers
{
    public static string FormattedNameDefault(this ITestUser user)
    {
        return user.lastName + ", " + user.firstName;
    }
}

public class TestUser : ITestUser
{
    public int id { get; set; }
    public string firstName { get; set; }
    public string lastName { get; set; }

    public string FormattedName()
    {
        return this.FormattedNameDefault();
    }
}

编辑* 重要的是,您实现的扩展方法和方法的命名方式不同,否则您可能会获得堆栈溢出。

答案 4 :(得分:2)

在C#8.0中是可能的。您可以添加具有默认实现的方法。您必须将目标框架版本更改为最新版本才能使用此功能。

答案 5 :(得分:0)

作为一名Newbe C#程序员,我正在阅读此主题,并想知道以下代码示例是否有帮助(我什至不知道这是否是正确的方法)。对我来说,它允许我在接口后面编码默认行为。请注意,我使用通用类型规范来定义(抽象)类。

namespace InterfaceExample
{
    public interface IDef
    {
        void FDef();
    }

    public interface IImp
    {
        void FImp();
    }

    public class AbstractImplementation<T> where T : IImp
    {
        // This class implements default behavior for interface IDef
        public void FAbs(IImp implementation)
        {
            implementation.FImp();
        }
    }

    public class MyImplementation : AbstractImplementation<MyImplementation>, IImp, IDef
    {
        public void FDef()
        {
            FAbs(this);
        }
        public void FImp()
        {
            // Called by AbstractImplementation
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            MyImplementation MyInstance = new MyImplementation();

           MyInstance.FDef();
        }
    }
}