1.接口定义
接口的正式定义:接口就是一组抽象成员的结合.
正确接口代码例子:
// 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...");
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。
{
}
现在我来实现ComparaTo方法如下:
{
// 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();
}