我有以下代码:
interface ICalculator
{
int Sum ( int x, int y);
}
abstract class AbsCalculator
{
public abstract int Sum(int x, int y);
}
class Calculator : AbsCalculator, ICalculator
{
public override int Sum(int x, int y)
{
Console.WriteLine ( "From overriden method" );
return x + y;
}
}
以下语句工作正常,程序编译尽管我没有实现接口:
Calculator calculator = new Calculator();
Console.WriteLine ( calculator.Sum(10, 20) );
所以我的第一个问题是:它为什么有效?
然后,我将以下接口实现添加到Calculator类:
int ICalculator.Sum(int x, int y)
{
Console.WriteLine("From implemented method");
return x + y;
}
再次尝试以下声明时:
Calculator calculator = new Calculator();
Console.WriteLine ( calculator.Sum(10, 20) );
该方法覆盖了仍然被调用的抽象。 所以我的第二个问题是:为什么程序从抽象类调用方法而不是从接口调用方法?
答案 0 :(得分:5)
有两种方法可以在C#中实现接口,无论是显式还是隐式,但CLR只有一种类型的实现 - 显式的。
当C#编译器发现某个类必须实现一个接口时,它会查找与该接口所需类的签名匹配的方法,并指示CLR这些是实现,以保存代码。
因此,在您的情况下,当C#编译器发现您的类实现了ICalculator时,它将查找与Sum(int,int)的签名匹配的公共方法,并将该方法视为实现。该方法被覆盖的事实并不重要。
如果你想为方法的实现赋予另一种含义,你应该明确地给它。
答案 1 :(得分:4)
不,你是要求它!您的第一个代码块完全合法。名称和签名与界面要求匹配:int Sum(int x, int y)
。
现在,int ICalculator.Sum(int x, int y)
之类的签名称为explicit interface implementation,这意味着您只能 通过接口类型的引用访问该方法。
interface ICalculator {
int Sum ( int x, int y);
}
abstract class AbsCalculator {
public abstract int Sum(int x, int y);
}
class Calculator : AbsCalculator, ICalculator {
public override int Sum(int x, int y) {
Console.WriteLine ( "From overriden method" );
return x + y;
}
int ICalculator.Sum(int x, int y) {
Console.WriteLine("From explicitly implemented interface method");
return x + y;
}
}
class Program {
static void Main() {
Calculator calculator = new Calculator();
ICalculator icalc = calculator;
// These calls will print different messages.
calculator.Sum(10,20);
icalc.Sum(10,20);
}
}
答案 2 :(得分:4)
回答您的第一个问题
在.NET中加载类型(Class)时,CLR会创建一个方法表,该表包含由类定义的方法的条目以及类继承的方法,因此在您的情况下Calculator
class包含以下条目
默认情况下,每个类都隐式继承自Object
基类,因此方法表包含Object
类定义的每个虚拟实例方法的条目。
您的类继承自AbsCalculator
抽象类,因此方法表定义了抽象类方法的条目Sum
您的类继承ICalculator
接口,因此方法表定义了接口Sum
方法的条目。
这里C#编译器假设您正在实现接口方法,因为该方法是Public
并且接口方法和抽象类方法的签名是相同的。所以编译器没有给出任何错误
回答第二个问题
实施时有两个概念Implicit Interface Method Implementation
和Explicit Interface Method Implementation
在Implicit Interface Method Implementation
中,我们使用接口引用调用接口方法,如下所示
Calculator calculator = new Calculator();
ICalculator icalc = calculator;
calculator.Sum(5,5);
icalc.Sum(5,10);
在Explicit Interface Method Implementation
中,当您使用接口名称为方法名称添加前缀时,它将成为显式方法实现。
interface ICalc
{
int Sum(int x, int y);
}
abstract class AbsCalc
{
public abstract int Sum(int x, int y);
}
class Program : AbsCalc, ICalc
{
public override int Sum(int x, int y)
{
Console.WriteLine("From abstract Override");
return x + y;
}
int ICalc.Sum(int x,int y)
{
Console.WriteLine("From Intrface");
return x + y;
}
static void Main(string[] args)
{
Program p = new Program();
p.Sum(1, 2);
ICalc i = p;
i.Sum(1,2);
}
}