在接口中声明成员函数
本文关键字:成员 函数 声明 接口 | 更新日期: 2023-09-27 17:56:00
首先,我对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# 中的接口来做到这一点。
在 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
派生出来,并通过集成ConcreteMyInterface
的功能来实现IMyInterface
:
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");
}
}
}
直接处理这个问题的唯一方法是使用抽象类,因为接口不能包含任何形式的"逻辑",而只是一个契约。
但是,一种替代方法是创建一个接口和一个静态类。 然后,您可以使用接口将逻辑放在扩展方法中。
public interface IMyInterface {
void Function();
}
public static class MyInterfaceExtensions {
public static void MyAction(this IMyInterface object)
{
// use object.Function() as needed
}
}
这里的主要缺点是类型更多,这会降低可维护性,并且缺乏可发现性。
您可以将MyAction
定义为扩展方法:
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();
}
}
输出:
世界您好
接口无法实现任何行为,它们只是合约。如果你想在定义合约时实现一些逻辑,你可以使用抽象类。
为此. 您需要定义抽象类。可以提供默认实现,也可以将实现留给派生类。
如果派生类想要覆盖某些东西,他们总是可以这样做。这使他们能够灵活地使用 base 以及他们想要覆盖的更改。
在接口中声明函数的接口(签名和返回类型),然后创建一个为实现该接口而定义的抽象类,并在抽象类中实现基本的默认实现。 然后,创建从抽象类继承的其他具体类,但在必要时,使用不同的实现重写抽象类基实现。
这种问题最好通过分离外部行为来克服; 在这种情况下,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 void MyFunction();
}
最后,一个具体的实现,它以某种特定的方式处理MyFunction的结果;
class ConcreteClass : BaseClass
{
protected override void MyFunction()
{
// concrete implementation here
}
}
接口是一个协定,不能包含实现。
从你上面的陈述中:
我可以使用抽象类而不是接口,但这样我就无法从其他类继承
我相信你正在解决"为什么C#不支持多重继承"的问题。
下面是一篇关于 C# 的模拟多重继承的代码项目文章。 您应该能够遵循此模式来实现 C# 简单继承模型的解决方法。
这是 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