例如,假设我想要一个ICar接口,并且所有实现都将包含该字段Year.这是否意味着每个实现都必须单独声明Year?简单地在界面中定义它不是更好吗?
Eri*_*ert 230
虽然许多其他答案在语义层面上是正确的,但我发现从实现细节层面处理这些问题也很有趣.
接口可以被认为是包含方法的插槽集合.当类实现接口时,该类需要告诉运行时如何填充所有必需的槽.当你说
interface IFoo { void M(); }
class Foo : IFoo { public void M() { ... } }
Run Code Online (Sandbox Code Playgroud)
该类说"当你创建我的实例时,在IFoo.M的插槽中填写对Foo.M的引用.
然后当你打电话时:
IFoo ifoo = new Foo();
ifoo.M();
Run Code Online (Sandbox Code Playgroud)
编译器生成的代码"询问对象在IFoo.M的插槽中有什么方法,并调用该方法.
如果接口是包含方法的插槽集合,那么其中一些插槽还可以包含属性的get和set方法,索引器的get和set方法以及事件的add和remove方法.但是一个领域不是一种方法.没有与某个字段相关联的"插槽",您可以随后通过对字段位置的引用来"填充"该字段.因此,接口可以定义方法,属性,索引器和事件,但不能定义字段.
LBu*_*kin 130
C#中的接口旨在定义类将遵守的合同 - 而不是特定的实现.
本着这种精神,C#接口确实允许定义属性 - 调用者必须为以下内容提供实现:
interface ICar
{
int Year { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
如果没有与属性关联的特殊逻辑,则实现类可以使用自动属性来简化实现:
class Automobile : ICar
{
public int Year { get; set; } // automatically implemented
}
Run Code Online (Sandbox Code Playgroud)
Tar*_*don 51
将其声明为属性:
interface ICar {
int Year { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
Han*_*ant 35
Eric Lippert钉了它,我会用不同的方式说出他说的话.接口的所有成员都是虚拟的,它们都需要被继承接口的类覆盖.您没有在接口声明中显式编写virtual关键字,也没有在类中使用override关键字,它们是隐含的.
virtual关键字在.NET中使用方法和所谓的v-table(方法指针数组)实现.override关键字用不同的方法指针填充v表槽,覆盖基类生成的那个.属性,事件和索引器作为方法实现.但是领域不是.因此,接口不能包含字段.
Joh*_*lla 19
为什么不拥有一个Year属性,这是完美的?
接口不包含字段,因为字段表示数据表示的特定实现,并且公开它们会破坏封装.因此,具有字段的接口将有效地编码到实现而不是接口,这对于接口来说是一个奇怪的悖论!
例如,您的Year规范的一部分可能要求ICar实施者无法分配到Year晚于当前年份+ 1或1900年之前的部分.如果您有暴露的Year字段,则无法说明- 更好用而不是在这里做工作.
Ada*_*son 18
简短的回答是肯定的,每个实现类型都必须创建自己的支持变量.这是因为界面类似于合同.它所能做的只是指定实现类型必须提供的特定公共可访问代码段; 它本身不能包含任何代码.
使用您的建议考虑这种情况:
public interface InterfaceOne
{
int myBackingVariable;
int MyProperty { get { return myBackingVariable; } }
}
public interface InterfaceTwo
{
int myBackingVariable;
int MyProperty { get { return myBackingVariable; } }
}
public class MyClass : InterfaceOne, InterfaceTwo { }
Run Code Online (Sandbox Code Playgroud)
我们在这里有几个问题:
myBackingVariable会MyClass用?最常用的方法是声明接口和实现它的准系统抽象类.这使您可以灵活地继承抽象类并免费获得实现,或者显式实现接口并允许从其他类继承.它的工作原理如下:
public interface IMyInterface
{
int MyProperty { get; set; }
}
public abstract class MyInterfaceBase : IMyInterface
{
int myProperty;
public int MyProperty
{
get { return myProperty; }
set { myProperty = value; }
}
}
Run Code Online (Sandbox Code Playgroud)
其他人给出了"为什么",所以我只想补充说你的界面可以定义一个控件; 如果你将它包装在一个属性中:
public interface IView {
Control Year { get; }
}
public Form : IView {
public Control Year { get { return uxYear; } } //numeric text box or whatever
}
Run Code Online (Sandbox Code Playgroud)
已经说了很多了,但为了简单起见,这是我的看法。接口旨在具有由消费者或类实现的方法契约,而不具有用于存储值的字段。
您可能会争论那为什么允许财产呢?所以简单的答案是 - 属性仅在内部定义为方法。
| 归档时间: |
|
| 查看次数: |
137570 次 |
| 最近记录: |