[英]Can a C# class call an interface's default interface method from its own implementation?
如果我有這樣的默認接口方法:
public interface IGreeter
{
void SayHello(string name) => System.Console.WriteLine($"Hello {name}!");
}
我可以讓我的具體實現調用該默認方法嗎?
public class HappyGreeter : IGreeter
{
public void SayHello(string name)
{
// what can I put here to call the default method?
System.Console.WriteLine("I hope you're doing great!!");
}
}
所以調用:
var greeter = new HappyGreeter() as IGreeter;
greeter.SayHello("Pippy");
結果如下:
// Hello Pippy!
// I hope you're doing great!!
實際上,從實現 class 調用 C# 接口默認方法表明我可以調用我的 class未實現的方法,但正如預期的那樣,添加對((IGreeter)this).SayHello(name);
在HappyGreeter.SaysHello
內部會導致堆棧溢出。
據我所知,您不能在繼承 class 時調用默認接口方法實現(盡管有建議)。 但是你可以從繼承接口調用它:
public class HappyGreeter : IGreeter
{
private interface IWorkAround : IGreeter
{
public void SayHello(string name)
{
(this as IGreeter).SayHello(name);
System.Console.WriteLine("I hope you're doing great!!");
}
}
private class WorkAround : IWorkAround {}
public void SayHello(string name)
{
((IWorkAround)new WorkAround()).SayHello(name);
}
}
UPD
在我最初的答案中,我非常想表明您可以在繼承接口中調用base
,但正如@Alexei Levenkov在評論中建議的那樣,在這種特殊情況下,更簡潔的方式將是這樣的:
public class HappyGreeter : IGreeter
{
private class WorkAround : IGreeter { }
private static readonly IGreeter _workAround = new WorkAround();
public void SayHello(string name)
{
_workAround.SayHello(name);
System.Console.WriteLine("I hope you're doing great!!");
}
}
我知道這不是問題的答案,但下一種方法也可用於模擬base
功能:
public interface IGreeter
{
void SayHello(string name) => BaseSayHello(name);
// This static method can be used in implementers of "IGreeter"
// to emulate "base" functionality.
protected static void BaseSayHello(string name) => System.Console.WriteLine($"Hello {name}!");
}
public class HappyGreeter : IGreeter
{
public void SayHello(string name)
{
IGreeter.BaseSayHello(name);
Console.WriteLine("I hope you're doing great!!");
}
}
有一個非常簡單的方法來處理這個:
此代碼適用於 C#8 或更高版本,如果針對 .NET 框架構建,它將不起作用。 我用 C#9 在 Windows 10 上運行它,在 .NET 6 上運行,預覽 5。
例子:
public interface IGreeter
{
private static int DisplayCount = 0;
public static void SayHello(string name)
{
DisplayCount++;
Console.WriteLine($"Hello {name}! This method has been called {DisplayCount} times.");
}
}
public class HappyGreeter : IGreeter
{
public void SayHello(string name)
{
// what can I put here to call the default method?
IGreeter.SayHello(name);
Console.WriteLine("I hope you're doing great!!");
}
}
public class CS8NewFeatures
{
// This class holds the code for the new C# 8 features.
//
public void RunTests()
{
TestGreeting();
}
private void TestGreeting()
{
// Tests if a default method may be called after a class has implemented it.
//
var hg = new HappyGreeter();
hg.SayHello("Pippy");
hg.SayHello("Bob");
hg.SayHello("Becky");
}
}
示例 Output:
Hello Pippy! This method has been called 1 times.
I hope you're doing great!!
Hello Bob! This method has been called 2 times.
I hope you're doing great!!
Hello Becky! This method has been called 3 times.
I hope you're doing great!!
Static 字段現在也允許在接口中,如本示例所示。
如果由於某種原因您不能使用 static 接口方法,那么您始終可以依賴以下技術:
例子:
public class DefaultMethods
{
// This class is used to show that a static method may be called by a default interface method.
//
public static void SayHello(string name) => Console.WriteLine($"Hello {name}!");
}
public interface IGreeter
{
void SayHello(string name) => DefaultMethods.SayHello(name);
}
public class HappyGreeter : IGreeter
{
public void SayHello(string name)
{
// what can I put here to call the default method?
DefaultMethods.SayHello(name);
Console.WriteLine("I hope you're doing great!!");
}
}
public class CS8NewFeatures
{
// This class holds the code for the new C# 8 features.
//
public void RunTests()
{
TestGreeting();
}
private void TestGreeting()
{
// Tests if a default method may be called after a class has implemented it.
//
var hg = new HappyGreeter();
hg.SayHello("Bob");
}
}
樣品 Output:
Hello Bob!
I hope you're doing great!!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.