是否可以在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#中没有多重继承而且它与有接口的默认实现(如果可能!)。
答案 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();
}
}
}