第四周章老师详细讲了C#有关接口,数组以及字符串方面的知识,由于后两者知识点太过零碎,不太容易记录,所以本次学习记录就只讨论一下接口。
接口,使用interface关键字进行声明,功能是把所需成员组合起来,以封装一定功能的集合。它好比一个模板,在其中定义了对象必须实现的成员,通过类或结构来实现它。
需要牢牢记住的是:接口不能直接实例化,接口不能包含成员的任何代码,只定义成员本身。接口成员的具体代码由实现接口的类提供。
接口的声明格式如下列代码所示:
1 [attributes] [access-modifiers] interface interface-name [:base-inteface-list] 2 { 3 interface body 4 }
各项释义
attributes(可选):附加的定义性信息。
access-modifiers(可选):允许使用的修饰符有 new 和四个访问修饰符。分别是:new、public、protected、internal、 private。在一个接口定义中同一修饰符不允许出现多次,new 修饰符只能出现在嵌套接口中,表示覆盖了继承而来的同名成员。public, protected, internal, private 修饰符定义了对接口的访问权限,默认值是internal。
interface-name :接口名, 习惯上以大写 I 开头。
base-inteface-list(可选):包含一个或多个显式基接口的列表,接口间由逗号分隔。
interface body :接口主体(不能有访问修饰符),只是定义接口的方法和属性等的签名,实际的实现是写在使用该接口的class里。
实际接口声明代码示例如下:
1 public interface IStorable 2 { 3 void Read( );//注意这里一定不能有public之类的修饰符 4 void Write(object);//并且只是签名,不能有实际内容 5 }
接口的继承使用示例如下:
1 public class Document : IStorable//如继承一般类一般继承接口 2 { 3 public void Read( ) {...}//这里可以加修饰符了,并写出实现代码 4 public void Write(object obj) {...} 5 // ... 6 }
一个类是可以继承多个接口的,代码示例如下:
1 interface ICompressible//定义新接口 2 { 3 void Compress(); 4 void Decompress(); 5 }
6 public class Document : IStorable, ICompressible 7 { 8 //实现IStorable 9 public void Read( ) {...} 10 public void Write(object obj) {...} 11 // 实现ICompressible 12 public void Compress(){ …} 13 public void Decompress() { …} 14 }
另外,接口也是可以继承接口的,代码示例如下:
1 interface ILoggedCompressible 2 : ICompressible 3 { 4 void LogSavedBytes(); 5 } 6 7 public class Document : ILoggedCompressible 8 { 9 // 实现ICompressible 10 public void Compress(){ …} 11 public void Decompress() { …} 12 // 实现ILoggedCompressible 13 public void LogSavedBytes() { …} 14 }
接口继承接口不用实现继承的接口中的方法,不过一个类继承一个有继承其他接口的接口时,一定要实现继承链上所有接口中的所有方法,不然就会报错。
同时,接口也是可以同时继承多个接口的,代码示例如下:
1 interface IStorableCompressible 2 : IStorable, ILoggedCompressible//同时继承两个接口 3 { 4 void LogOriginalSize(); //增加的新方法 5 }
看到上面复杂的继承关系,是不是很眼晕?一想到在开发中要记住这么多的继承关系就感觉整个人就要炸了。不过不要担心,我们可以利用C#提供的的关键字as检查是否继承了某个接口,此法也适用于普通类的继承检查,用好了可以帮我们节省大量功夫。
可以使用 as 运算符执行转换的某些类型在兼容之间的引用类型或可以为null的类型。如下列代码所示:
1 foreach (Document doc in folder) 2 { 3 IStorable isDoc = doc as IStorable; 4 //如果doc继承了IStorable,则doc转为IStorable 5 if (isDoc != null) 6 { 7 isDoc.Read(); 8 } 9 //否则isDoc是null 10 else 11 { 12 Console.WriteLine("IStorable not supported"); 13 } 14 … 15 }
有时候继承多个接口的时候,会遇到两个接口中定义了签名相同的方法,如下列代码所示:
1 interface IStorable 2 { 3 void Read(); 4 void Write(); 5 } 6 7 interface ITalk 8 { 9 void Talk(); 10 void Read(); 11 }
此时在派生类里定义两个Read方法时就要注意了,定义的方法包括显式定义与隐式定义,如下列代码所示:
1 public class Document : IStorable, ITalk 2 { 3 public Document(string s) 4 {…; } 5 // IStorable的Read方法,隐式定义 6 public virtual void Read() 7 {…; } 8 public void Write() 9 {…; } 10 //ITalk的Read方法,显式定义 11 void ITalk.Read() 12 { …; } 13 public void Talk() 14 { …; } 15 }
需要注意的是显示定义的方法不能有访问修饰符, 隐式为 public!
另外需要注意的是两种定义方法的调用问题,如下列代码所示:
1 ...2 //隐式定义的方法正常通过对象调用 3 Document theDoc = new Document(“Test”); 4 theDoc.Read(); 5 //显式定义的方法调用时要将对象转为对应接口类型 6 ITalk itDoc = theDoc; 7 itDoc.Read(); 8 ...
需要牢记显式实现的接口方法对一般对象是不可见的,无法调用,必须转换类型。
本次学习记录到此为止。以后有机会会补上或修正错误之处。
请各位大大不吝赐教!