C#2008与.NET 3.5 高级程序设计读书笔记(9)--接口

1.接口定义

接口的正式定义:接口就是一组抽象成员的结合.

(1).一个接口定义了一个契约。
(2).接口可以包容方法、C#属性、事件、以及索引器。
(3).在一个接口声明中,我们可以声明零个或者多个成员。
(4).所有接口成员的默认访问类型都是public。
(5).如果在接口成员声明中包括了任何修饰符,那么会产生一个编译器错误。  

正确接口代码例子:

代码
    
      
// IDbConnection接口定义了一组所有连接对象都支持的公共的成员。
public interface IDbConnection : IDisposable
{
// 方法
IDbTransaction BeginTransaction();
IDbTransaction BeginTransaction(IsolationLevel il);
void ChangeDatabase( string databaseName);
void Close();
IDbCommand CreateCommand();
void Open();
// 属性
string ConnectionString { get ; set ;}
int ConnectionTimeout { get ; }
string Database { get ; }
ConnectionState State {
get ; }
}

错误接口代码例子

代码
    
      
// 内有大量错误!
public interface IPointy
{
// 错误!接口不能有字段!
public int numbOfPoints;
// 错误!接口不能有构造函数!
public IPointy() { numbOfPoints = 0 ;};
// 错误!接口不能提供实现!
byte GetNumberOfPoints() { return numbOfPoints; }

}

2.对比接口类型和抽象基类

虽然类类型定义了一组抽象成员,它完全可以再定义许多构造函数、字段数据、非抽象成员(具有实现)等。而接口,只能包含抽象成员。

和抽象类的相似之处有三点:
1、不能实例化;
2、包含未实现的方法声明;
3、派生类必须实现未实现的方法,抽象类是抽象方法,接口则是所有成员(不仅是方法包括其他成员);

另外,接口有如下特性:
接口除了可以包含方法之外,还可以包含属性、索引器、事件,而且这些成员都被定义为公有的。除此之外,不能包含任何其他的成员,例如:常量、域、构造函数、析构函数、静态成员。
一个类可以直接继承多个接口,但只能直接继承一个类(包括抽象类)。

由抽象父类创建的多态接口有一个主要的限制,那就是只有派生类型才支持由抽象父类定义的成员。然而,在大型软件系统中,开发除了System.Object之外没有公共父类的多个类层次结构很普遍。由于抽象基类中的抽象成员只应用到派生类型,我们就不能以多个层次结构配置类型来支持相同的多态接口。

3.获取接口引用is和as关键字

代码
    
      
// 生成Shape类型的数组,使其中部分成员实现了IPointy接口。
Shape[] s = { new Hexagon(), new Circle(), new Triangle( " Joe " ),
new Circle( " JoJo " )} ;
for ( int i = 0 ; i < s.Length; i ++ )
{
// 哪些是有棱角的?
if (s[i] is IPointy)
Console.WriteLine(
" -> Points: {0} " , ((IPointy)s[i]).Points);
else
Console.WriteLine(
" -> {0}\'s not pointy! " , s[i].PetName);
Console.WriteLine();
}
代码
    
      
// 我们能将六角形hex2视为实现了IPointy接口吗?
Hexagon hex2 = new Hexagon( " Peter " );
IPointy itfPt2
= hex2 as IPointy;
if (itfPt2 != null )
Console.WriteLine(
" Points: {0} " , itfPt2.Points);
else
Console.WriteLine(
" OOPS! Not pointy... " );
4.接口的常用使用方法:

(1).接口作为参数
代码
     
       
static void DrawIn3D(IDraw3D itf3d)
{
itf3d.Draw3D();
}
// 调用代码
Shape[] s = { new Hexagon(), new Circle(),
new Triangle(), new Circle( " JoJo " ) } ;
for ( int i = 0 ; i < s.Length; i ++ )
{
// 支持绘制为3D吗?
if (s[i] is IDraw3D)
DrawIn3D((IDraw3D)s[i]);
}

(2).接口作为返回值

代码
     
       
// 这个方法检查对象是否支持IPointy接口,
// 如果是,返回一个接口引用。
static IPointy ExtractPointyness( object o)
{
if (o is IPointy)
return (IPointy)o;
else
return null ;
}
// 调用方法
// 试图从ints对象获取IPointy接口。
int [] myInts = { 10 , 20 , 30 };
IPointy itfPt
= ExtractPointyness(myInts);
if (itfPt != null )
Console.WriteLine(
" Object has {0} points. " , itfPt.Points);
else
Console.WriteLine(
" This object does not implement IPointy " );

(3).接口类型数组

 同样的接口即使不在同一个类层次结构,也没有除System.Object以外的公共父类,也可以由多个类型实现,这可以派生出许多非常强大的编程构造。

代码
    
      
// 这个数组仅仅包含实现了IPointy接口的类型。
IPointy[] myPointyObjects = { new Hexagon(), new Knife(),
new Triangle(), new Fork(), new PitchFork()};
foreach (IPointy i in myPointyObjects)
Console.WriteLine(
" Object has {0} points. " , i.Points);

5.IEnumerable 和 IEnumerator 接口

IEnumerable:

IEnumerator GetEnumerator() 返回可循环访问集合的枚举数。

公开枚举数,该枚举数支持在非泛型集合上进行简单迭代。

该接口只定义了一个函数:GetEnumerator,通过该函数返回一个循环访问集合的枚举数。

若要支持foreach语义则须实现此接口。

IEnumerator:

object Current 获取集合中的当前元素。
bool MoveNext() 将枚举数推进到集合的下一个元素。
如果枚举数成功地推进到下一个元素,则为 true;如果枚举数越过集合的结尾,则为 false
void Reset() 将枚举数设置为其初始位置,该位置位于集合中第一个元素之前。

IEnumerator 是所有非泛型枚举数的基接口。C# 语言的 foreach 语句(在 Visual Basic 中为 for each)隐藏了枚举数的复杂性。因此,建议使用 foreach,而不直接操作枚举数。

MSDN例子:

代码
   
     
using System;
using System.Collections;

public class Person
{
public Person( string fName, string lName)
{
this .firstName = fName;
this .lastName = lName;
}

public string firstName;
public string lastName;
}

public class People : IEnumerable
{
private Person[] _people;
public People(Person[] pArray)
{
_people
= new Person[pArray.Length];

for ( int i = 0 ; i < pArray.Length; i ++ )
{
_people[i]
= pArray[i];
}
}

public IEnumerator GetEnumerator()
{
return new PeopleEnum(_people);
}
}

public class PeopleEnum : IEnumerator
{
public Person[] _people;

// Enumerators are positioned before the first element
// until the first MoveNext() call.
int position = - 1 ;

public PeopleEnum(Person[] list)
{
_people
= list;
}

public bool MoveNext()
{
position
++ ;
return (position < _people.Length);
}

public void Reset()
{
position
= - 1 ;
}

public object Current
{
get
{
try
{
return _people[position];
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
}

class App
{
static void Main()
{
Person[] peopleArray
= new Person[ 3 ]
{
new Person( " John " , " Smith " ),
new Person( " Jim " , " Johnson " ),
new Person( " Sue " , " Rabon " ),
};

People peopleList
= new People(peopleArray);
foreach (Person p in peopleList)
Console.WriteLine(p.firstName
+ " " + p.lastName);

}
}

/* This code produces output similar to the following:
*
* John Smith
* Jim Johnson
* Sue Rabon
*
*/

教材上的例子:

代码
   
     
using System;
using System.Collections
public class Garage : IEnumerable
{
// System.Array已经实现了IEnumerator!
private Car[] carArray = new Car[ 4 ];
public Garage()
{
carArray[
0 ] = new Car( " FeeFee " , 200 , 0 );
carArray[
1 ] = new Car( " Clunker " , 90 , 0 );
carArray[
2 ] = new Car( " Zippy " , 30 , 0 );
carArray[
3 ] = new car( " Fred " , 30 , 0 );
}
public IEnumerator GetEnumerator()
{
// 返回数组对象的IEnumerator。
return carArray.GetEnumerator();
}
}

6.IComparable接口

IComparable接口用来支持在集合中排序。它有一个函数——CompareTo。当你设计分类对象时,你必须实现IComparable的CompareTo方法。

比如,我做一个Developer类来继承IComparable。

public   class  Developer : IComparable
{
}

现在我来实现ComparaTo方法如下:

public   int  CompareTo( object  obj)
{
// Some code here
}

现在我们说,Developer类有一个属性叫ID,而你希望你的这些项目按照ID来排序,我们简单的加入如下代码:

 

代码
   
     
public int CompareTo( object obj)

{

if ( ! (obj is Developer) )

throw new InvalidCastException( " Not a valid Developer object. " );

Developer developer
= (Developer)obj;

return this .ID.CompareTo(developer.ID);
// 使用IComparable为他们排序
// Array.Sort();

}

 

你可能感兴趣的:(.net)