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; //没有错误 }