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();

}

 

posted @ 2010-07-05 14:26  自助者天助  阅读(211)  评论(0编辑  收藏  举报