基 础-----接口

 
定义接口的语法如下:
 
[attributes] [access-modifier] interface interface-name[:base-list]
{interface-body}
 
接口的目的是定义一些类所应具有的功能。
 
interface IStorable{
 void Read( );
 void Write( object obj );
 int Status { get; set; }
}
 
interface ICompressible
{
 void Compress( );
 void Decompress( );
}
 
继承自接口的类必须实现接口声明的所有方法和属性。
 
接口中的方法不需要加 访问修饰符(access-modifier) ,否则会产生编译错误。接口中的方法隐式的被声明为public,因为接口是一个由其他类所使用的契约(contract)。
 
不能创建接口的实例,只能创建实现了接口的类的实例。实现了接口的类的实例,可以转换为这一接口类型。
 
WARNING:实现接口的类中的方法不可以是静态的(static)。
实现多个接口
public class Document : IStorable, ICompressible
扩展接口
interface ILoggedCompressible : ICompressible
{
    void LogSavedBytes();
}
复合接口
interface IStorableCompressible : IStorable, ILoggedCompressible
{
     void LogOriginalSize();
}
将类的实例转换为接口类型
Public class Document:IStorableCompressible
{
 // implemention
}
 
Document doc = new Document();
IStorable isDoc = doc as IStorable;
IStorableCompressible iscDoc = doc as IStorableCompressible;
 
其中 IStorable isDoc = doc as IStorable也可直接写作 IStorable isDoc = doc
因为编译器知道Document类实现了IStorable接口,并会进行隐式转换。
 
如果不确定某个类是否实现了 IStrorable 接口,可以使用 as ,如果该类没有实现,将返回null。
 
IStrorable icDoc = someClassInstance as IStrorable;
if ( icDoc != null )
{
   icDoc.Read( );
}
else
   Console.WriteLine( "Read not supported" );
访问接口方法
以多态方式使用接口。
 
IStorable isDoc = new Document("Test Document");
icDoc.Read( );
将对象转换成接口类型
很多情况下,并不知道集合中的某个对象是否实现了接口。如果像下面这样使用接口:
 
Document doc = myCollection[0];
 
IStorable isDoc = (IStorable) doc;
isDoc.Read( );
 
ICompressible icDoc = (ICompressible) doc;
icDoc.Compress( );
 
而 Document的声明是这样的:
 
public class Document : IStorable
 
则将抛出异常。
使用 is 操作符
为了判断某个对象是否实现了特定接口,可以使用 is 操作符:
 
expression is type
 
如果 expression 可以转换成 type类型,则上面的表达式返回 true。
 
使用 is 的范例:
 
if (doc is IStorable)
{
 IStorable isDoc = (IStorable)doc;
 isDoc.Read( );
}
使用 as 操作符
也可以使用 as ,当某个对象不能转换为特定接口时,将返回 null。
 
expression as type
 
使用 as 的范例:
 
IStorable isDoc = doc as IStorable;
if (isDoc != null)
{
 isDoc.Read( );
}
 
在类型转换时使用 as 优于使用 is(原因略)
抽象类 vs 接口
很多情况下 抽象类 和 接口可以互相转换,而且区别甚微。
abstract class Storable
{
 abstract public void Read();
 abstract public void Write();
}
 
使用接口的理由:
l         可以继承多个接口,但只能继承一个抽象类
 
使用抽象类的理由:
l         抽象类可以更好的进行版本控制。如果日后修改一个抽象类,只需再往里添加一个虚拟方法,并提供一个默认实现。而对于一个接口,如果添加一个新方法,则只有两种可能:与此接口相关的所有类都必须改写,以实现这个新添加的方法;可以新起一个接口,并让这个接口继承自老接口,如此一来,你将会获得非常多的接口,很难管理。
覆盖接口实现的方法
一个实现了接口的类,可以将实现接口的任何或者全部方法设为虚拟的。这样,继承此类的其他类可以对这些方法进行覆盖。
 
using System;
using System.Collections.Generic;
using System.Text;
 
namespace overridingInterface {
  interface IStorable {
      void Read();
      void Write();
 }
 
  /* 实现 IStorable 的简单 Document
  * ***************************************/
  public class Document : IStorable {
 
      public Document(string s) {
          Console.WriteLine("Creating document with: {0}", s);
      }
 
      // 虚拟方法
      public virtual void Read() {
          Console.WriteLine("Document Read Method for IStorable");
      }
 
      public void Write() {
          Console.WriteLine("Document Write Method for IStorable");
      }
 }
 
  /* 继承自 Document 的类
  * ***************************************/
  public class Note : Document {
      public Note(string s): base(s) {
          Console.WriteLine("Creating note with: {0}", s);
      }
 
      // 覆盖 Document 中的虚拟方法
      public override void Read() {
          Console.WriteLine("Overriding the Read method for Note!");
      }
 
      // 实现一个 Note 的新 Write 方法
      public new void Write() {
          Console.WriteLine("Implementing the Write method for Note!");
      }
 }
 
  public class Tester {
 
      static void Main() {
          Document theDoc = new Document("** Doc");
          theDoc.Read();
          theDoc.Write();
 
          Console.WriteLine();
 
          IStorable isDoc = theDoc as IStorable;
          if (isDoc != null) {
              isDoc.Read();
              isDoc.Write();
          }
 
          Console.WriteLine("/n*************************************/n");
 
          Document theNote = new Note("** Fist Note");
          theNote.Read(); // 输出为覆盖了的 Read() 方法
          theNote.Write();
         
          Console.WriteLine();
         
          IStorable isNote = theNote as IStorable;
          if (isNote != null) {
              isNote.Read(); // 输出为覆盖了的 Read() 方法
              isNote.Write();
          }
 
          Console.WriteLine("/n*************************************/n");
 
          Note note2 = new Note("** Second Note");
          note2.Read();
          note2.Write();// 输出为使用 new 的,重新实现了的 Write() 方法
 
          Console.WriteLine();
 
          IStorable isNote2 = note2 as IStorable;
          if (isNote2 != null) {
              isNote2.Read();
              isNote2.Write();// 输出为 Document 实现的的方法
          }
 
          Console.ReadKey();
      }
 }
}
 
输出为:
Creating document with: ** Doc
Document Read Method for IStorable
Document Write Method for IStorable
 
Document Read Method for IStorable
Document Write Method for IStorable
 
*************************************
 
Creating document with: ** Fist Note
Creating note with: ** Fist Note
Overriding the Read method for Note!
Document Write Method for IStorable
 
Overriding the Read method for Note!
Document Write Method for IStorable
 
*************************************
 
Creating document with: ** Second Note
Creating note with: ** Second Note
Overriding the Read method for Note!
Implementing the Write method for Note!
 
Overriding the Read method for Note!
Document Write Method for IStorable
显式实现接口方法
当一个类实现了两个接口(假设Document 类实现了IStorable和ITalk接口),但是两个接口中有方法名相同时,可以使用下面的语法来显式地实现一个接口:
 
void ITalk.Read()
 
显式实现接口的方法时,不可以加访问修饰符(access modifier),将隐式地声明为public。
 
不能通过类的实例来直接访问显式实现的方法。假设该类还实现了IStorable接口中的Read()的方法,当使用下面的语句时:
 
theDoc.Read( );
 
将会隐式调用IStorable的Read() 方法。
 
如果该类仅实现了ITalk接口,而没有实现IStorable接口,也就不存在方法名冲突的情况,但是却仍使用显示的接口声明,那么当使用 theDoc.Read() 时,将会出现编译错误。
 
'ExplicitImplementation.Document' does not contain a definition for 'Read' F:/MyApp/Test/ExplictImplament.cs 57 11 Test
 
当想使用 ITalk接口的方法时,需要进行一次类型转换,使用下面的语法:
 
ITalk itDoc = theDoc;
itDoc.Read();
成员隐藏
假设有如下两个接口:
 
interface IBase
{
   int P { get; set; }
}
 
interface IDerived : IBase
{
   new int P();
}
 
继承 IDerived的类至少需要进行一个显示实现。
 
class myClass : IDerived
{
   int IBase.P { get {...} }
  
   public int P( ) {...}
}
 
class myClass : IDerived
{
   public int P { get {...} }
  
   int IDerived.P( ) {...}
}
 
class myClass : IDerived
{
   int IBase.P { get {...} }
  
   int IDerived.P( ) {...}
}
实现接口的值类型(Struct)
如果使用值类型实现接口,则应通过值类型的对象访问接口方法,而不要转换成接口,再用接口进行访问,此时会多出一个“复制”了的引用对象,而原来的值对象依然存在,两个对象是各自独立的。
 
myStruct theStruct = new myStruct( );
theStruct.Status = 2;
 
IStorable isTemp = ( IStorable ) theStruct;
Console.WriteLine( "isTemp: {0}", isTemp.Status );
 
isTemp.Status = 4;
Console.WriteLine("theStruct:{0}, isTemp: {1}",theStruct.Status, isTemp.Status );
 
theStruct.Status = 6;
Console.WriteLine( "theStruct: {0}, isTemp: {1}",theStruct.Status, isTemp.Status );
 
输出为:
 
isTemp: 2
theStruct: 2, isTemp: 4
theStruct: 6, isTemp: 4

你可能感兴趣的:(String,null,Class,interface,编译器,attributes)