我在C#.NET中编写了以下代码
public interface IWork
{
void func();
}
public abstract class WorkClass
{
public void func()
{
Console.WriteLine("Calling Abstract Class Function");
}
}
public class MyClass:WorkClass,IWork
{
}
编译时,我没有收到任何错误。编译器并没有强迫我实现方法“func();”在“MyClass”中,它来自接口“IWork”.Latter,我可以优雅地创建类“MyClass”的实例并调用函数“func()”。为什么编译器不强迫我在“MyClass”中实现“func()”方法(它来自“IWork”接口?这是C#中的一个缺陷吗?
答案 0 :(得分:9)
在阅读这个主题时,我发现我不能轻易地将它全部放在我的脑海里,所以我写下了一段代码,它充当了C#如何工作的备忘单。希望它可以帮到某人。
public interface IMyInterface
{
void FunctionA();
void FunctionB();
void FunctionC();
}
public abstract class MyAbstractClass : IMyInterface
{
public void FunctionA()
{
Console.WriteLine( "FunctionA() implemented in abstract class. Cannot be overridden in concrete class." );
}
public virtual void FunctionB()
{
Console.WriteLine( "FunctionB() implemented in abstract class. Can be overridden in concrete class." );
}
public abstract void FunctionC();
}
public class MyConcreteClass : MyAbstractClass, IMyInterface
{
public override void FunctionB()
{
base.FunctionB();
Console.WriteLine( "FunctionB() implemented in abstract class but optionally overridden in concrete class." );
}
public override void FunctionC()
{
Console.WriteLine( "FunctionC() must be implemented in concrete class because abstract class provides no implementation." );
}
}
class Program
{
static void Main( string[] args )
{
IMyInterface foo = new MyConcreteClass();
foo.FunctionA();
foo.FunctionB();
foo.FunctionC();
Console.ReadKey();
}
}
提供以下输出:
FunctionA()在抽象类中实现。在具体课堂上不能被覆盖。
FunctionB()在抽象类中实现。可以在具体课程中重写。
FunctionB()在抽象类中实现,但可以在具体类中重写。
FunctionC()必须在具体类中实现,因为抽象类不提供实现。
答案 1 :(得分:5)
为了更好地理解接口背后的概念,我只是给出正确的实现代码:
public interface IWork{
void func();
}
public abstract class WorkClass,IWork{
public void func(){
Console.WriteLine("Calling Abstract Class Function");
}
}
public class MyClass:WorkClass{
...
}
基本规则:您需要始终在实现所在的位置包含接口。因此,如果在抽象类中创建方法并定义此方法的接口,则需要将接口实现到抽象类中,然后所有子类将自动实现此接口。
事实上,接口有两种功能可以用于:
1)作为一个“真实”的接口,它提供了实现接口的任何类的通用处理,因此你可以通过一个接口处理几种类(不知道它们的真实类名)。 “处理”意味着:调用方法。
2)作为其他(框架)程序员的帮助,不要搞砸你的代码。如果要确保方法不会被其他名称替换,则可以为包含所有“必须”方法名称的类定义接口。即使该方法被调用,您的程序员在更改方法名称时也会收到编译错误消息。
现在,您可以通过界面Myclass
轻松处理IWork
。
答案 2 :(得分:3)
因为abstract
类实现了接口。
如果您的班级MyClass
不会继承WorkClass
,则会收到错误'MyClass' does not implement interface member 'IWork.func()'
。
但是你也从WorkClass
继承,它实际上实现了接口所需的方法。
如果要强制从其继承的类实现它,可以将func()
标记为抽象:
public abstract class WorkClass
{
public abstract void func();
}
答案 3 :(得分:1)
我在我的解决方案中尝试了上面的类。 它继承了抽象类,因此派生类具有func()方法定义。这就是它无法显示编译错误的原因。
答案 4 :(得分:0)
func()
未在abstract
中标记为WorkClass
,因此您无需在任何源自WorkClass
的类中实现它。
WorkClass
实现IWork
界面,因此您无需在MyClass
中实施该界面,因为它会从func()
继承WorkClass
。
答案 5 :(得分:0)
由于抽象类中的func方法是非虚方法,因此编译器认为此方法是接口的实现。
答案 6 :(得分:0)
当您将MyClass
扩展为WorkClass
时,方法func()
(已定义)将被继承。
因此,当实现接口IWork
时,已经定义了方法'func()'。因此,MyClass
中没有更多未定义的方法。
因此,类MyClass
是一个具体的类,因此您可以创建一个MyClass
对象而不会出现任何编译错误。