C#接口基础
示例
接口的功能称为功能的“合同”。这意味着它声明了属性和方法,但没有实现它们。
因此与类接口不同:
无法实例化
没有任何功能
只能包含方法*(属性和事件是内部方法)
继承接口称为“实现”
您可以从1类继承,但可以“实现”多个接口
public interface ICanDoThis{
void TheThingICanDo();
int SomeValueProperty { get; set; }
}注意事项:
“I”前缀是用于接口的命名约定。
函数主体将替换为分号“;”。
还允许使用属性,因为在内部它们也是方法
public class MyClass : ICanDoThis {
public void TheThingICanDo(){
//做事情
}
public int SomeValueProperty { get; set; }
public int SomeValueNotImplemtingAnything { get; set; }
}。
ICanDoThis obj = new MyClass(); //好 obj.TheThingICanDo(); //好 obj.SomeValueProperty = 5; //错误,该成员在界面中不存在 obj.SomeValueNotImplemtingAnything = 5; // in order to access the property in the class you must "down cast" it ((MyClass)obj).SomeValueNotImplemtingAnything = 5; //好
当您使用WinForms或WPF等UI框架时,这特别有用,因为从基类继承来创建用户控件是必须的,并且您失去了在不同控件类型上创建抽象的能力。一个例子?接下来:
public class MyTextBlock : TextBlock {
public void SetText(string str){
this.Text= str;
}
}
public class MyButton : Button {
public void SetText(string str){
this.Content= str;
}
}提出的问题是,两者都包含“文本”的某些概念,但是属性名称不同。而且您无法创建创建抽象基类,因为它们具有对2个不同类的强制继承。接口可以缓解
public interface ITextControl{
void SetText(string str);
}
public class MyTextBlock : TextBlock, ITextControl {
public void SetText(string str){
this.Text= str;
}
}
public class MyButton : Button, ITextControl {
public void SetText(string str){
this.Content= str;
}
public int Clicks { get; set; }
}现在MyButton和MyTextBlock是可互换的。
var controls = new List<ITextControls>{
new MyTextBlock(),
new MyButton()
};
foreach(var ctrl in controls){
ctrl.SetText("This text will be applied to both controls despite them being different");
//编译器错误,接口中没有此类成员
ctrl.Clicks= 0;
//运行时错误,因为实际上1类不是使此强制转换无效的按钮
((MyButton)ctrl).Clicks = 0;
/* the solution is to check the type first.
This is usually considered bad practice since
it's a symptom of poor abstraction */
var button = ctrl as MyButton;
if(button != null)
button.Clicks= 0; //没有错误
}