[英]Add common method to classes inheriting from a C# Interface?
I have an interface such as this one:我有一个这样的界面:
public interface ITestInterface
{
int a { get; set; }
void DoSomething();
}
Some of my classes are deriving from this interface:我的一些类是从这个接口派生的:
public class OneClass : ITestInterface
{
public int a { get; set; }
public void DoSomething()
{
Console.WriteLine(this.a.ToString());
}
}
public class AnotherClass : ITestInterface
{
public int a { get; set; }
public void DoSomething()
{
Console.WriteLine((this.a * 2).ToString());
}
}
Since I now need a (large) common method on all classes derived from my interface, I was trying to provide an additional base class for that:由于我现在需要在从我的接口派生的所有类上使用(大型)通用方法,因此我试图为此提供一个额外的基础 class:
public class MyBaseClass
{
public void LargeCommonMethod()
{
Console.WriteLine((this.a * 3).ToString()); // no 'a' on base class
}
}
This clearly doesn't work because the base class would also need to implement my interface in order to know about that a
field.这显然不起作用,因为基础 class 还需要实现我的接口才能了解
a
字段。
I am now asking myself what the best approach would be here:我现在问自己最好的方法是什么:
MyBaseClass
inherit from ITestInterface
?MyBaseClass
从ITestInterface
继承?LargeCommonMethod()
to protected
and provide all internal data it uses via arguments?LargeCommonMethod()
设置为protected
并通过 arguments 提供它使用的所有内部数据? (There's actually a lot of these..) C# 8 provides a feature precisely for this scenario. C# 8 正好为这种情况提供了一个功能。
That feature is default interface methods .该功能是默认接口方法。
You can add your method and a default implementation to the interface:您可以将您的方法和默认实现添加到接口:
public interface ITestInterface
{
int a { get; set; }
void DoSomething();
void LargeCommonMethod()
{
Console.WriteLine((this.a * 3).ToString());
}
}
Your existing classes that implement the interface will not break.您现有的实现该接口的类不会中断。 When cast as the interface, you'll be able to call the method which is defined in the interface.
当转换为接口时,您将能够调用接口中定义的方法。 You can still modify any class to provide its own implementation, overriding the interface's default implementation.
您仍然可以修改任何 class 以提供自己的实现,覆盖接口的默认实现。
For the method to be available the object must be cast as the interface - ITestInterface
.要使该方法可用,必须将 object 转换为接口 -
ITestInterface
。
A lot of developers - including myself - found this to be an odd feature.许多开发人员——包括我自己——发现这是一个奇怪的功能。 But this is the scenario it's for.
但这是它的场景。
The most common scenario is to safely add members to an interface already released and used by innumerable clients.
最常见的场景是将成员安全地添加到已被无数客户端发布和使用的接口中。
If you require a base implementation for a method then an interface is clearly not the way to go.如果您需要方法的基本实现,那么接口显然不是 go 的方式。
I would choose an abstract class instead and get rid of the interface.我会选择一个抽象的 class 代替并摆脱接口。 There is no need to complicate the design basically.
基本上没有必要使设计复杂化。
The Adapter pattern could fit your Use case, when you want to keep the ITestInterface consistent:当您希望保持 ITestInterface 一致时,适配器模式可能适合您的用例:
public interface ITestInterface
{
int a { get; set; }
void DoSomething();
}
public class TestInterfaceAdapter : ITestInterface
{
private readonly ITestInterface _testInterface;
public int a {
get => _testInterface.a;
set => _testInterface.a = value;
}
public TestInterfaceAdapter(ITestInterface testInterface)
{
_testInterface = testInterface;
}
public void DoSomething()
{
_testInterface.DoSomething();
}
public void LargeCommonMethod()
{
Console.WriteLine((this.a * 3).ToString());
}
}
public class OneClass : ITestInterface
{
public int a { get; set; }
public void DoSomething()
{
Console.WriteLine(this.a.ToString());
}
}
public class AnotherClass : ITestInterface
{
public int a { get; set; }
public void DoSomething()
{
Console.WriteLine((this.a * 2).ToString());
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.