目录
使用BCL中的接口IComparable 接口的示例 (269P)
什么是接口
接口是一种引用类型,它指定一组函数成员,但不实现它们。所以只能类和结构来实现接口。
先看一个使用接口的程序示例:
namespace HelloWorld_Console
{
interface IInfo //声明接口
{
string GetName();
string GetAge();
}
class CA: IInfo //声明一个类,该类实现了接口IInfo
{
public string Name;
public int Age;
//注意, 在类中实现接口的成员函数,该成员函数必须是public的,不能是其它的访问修饰符,否则错误
public string GetName()
{
return Name;
}
public string GetAge()
{
return Age.ToString();
}
}
class CB: IInfo
{
public string First;
public string Last;
public double PersonsAge;
public string GetName()
{
return First+ " "+Last;
}
public string GetAge()
{
return PersonsAge.ToString();
}
}
class Program
{
static void PrintInfo(IInfo item)
{
WriteLine($"Name:{item.GetName()},Age: {item.GetAge()}");
}
static void Main(string[] args)
{
CA a = new CA() { Name = "huangchengtao ", Age = 21 };
CB b = new CB() { First = "huangchengjian ", Last = "Doe", PersonsAge = 14 };
//对象的引用能自动转换为 它们实现的接口的引用
PrintInfo(a);
PrintInfo(b);
ReadKey();
}
}
}
我们不管传入什么样的类类型到函数PrintInfo ( )中,它都能正确的处理。
使用BCL中的接口IComparable 接口的示例 (269P)
先看一个代码示例:
class Program
{
static void Main(string[] args)
{
var myInt = new[] { 20, 4, 5, 6, 7, 8, 9 };
Array.Sort(myInt);
foreach(var tt in myInt)
{
WriteLine(tt);
}
ReadKey();
}
}
输出结果为:
4
5
6
7
8
9
20
Sort方法在int数组上工作得很好, 但是我们不可以在自定义的类或结构中使用,因为是它不知道如何比较用于自定义的对象以及如何进行排序。 Array 类的Sort方法其实依赖于一个叫做IComparable的接口,它声明在BCL中,包含唯一的方法CompareTo。
下面的代码是IComparable的接口的声明:
public interface IComparable
{
int ComparaTo(object obj); //该函数在接口中不能有实现
}
该函数的返回值有:
- 负数值——当前对象小于参数对象;
- 正数值 —— 当前对象大于参数对象
- 零 —— 两个对象在比较时相等。
Sort使用的算法可以使用元素的 CompareTo 方法来决定两个元素的次序。int类型实现了 IComparable, 但是自定义的类或结构没有, 因此当Sort尝试调用自定义的类或结构不存在的CompareTo方法时会抛出异常。
我们可以通过让类实现 IComparable 接口,来使 Sort 方法可以用于自定义的类或结构类型的对象。要实现一个接口,类或结构必须做两件事情:
- 必须在基类列表后面列出接口名称;
- 必须为接口的每一个成员提供实现。
下面看代码示例:
namespace HelloWorld_Console
{
class MyClass : IComparable // Class implements interface.
{
public int TheValue;
public int CompareTo(object obj) // Implement the method.
{
MyClass mc = (MyClass)obj;
if (this.TheValue < mc.TheValue)
return -1;
if (this.TheValue > mc.TheValue)
return 1;
return 0;
}
}
class Program
{
static void PrintOut(string s, params MyClass[] mc)
{
Console.Write(s);
foreach (var m in mc)
Console.Write("{0} ", m.TheValue);
Console.WriteLine("");
}
static void Main(string[] args)
{
var myInt = new[] { 20, 4, 16, 9, 2 };
MyClass[] mcArr = new MyClass[5]; // Create array of MyClass objs.
for (int i = 0; i < 5; i++) // Initialize the array.
{
mcArr[i] = new MyClass();
mcArr[i].TheValue = myInt[i];
}
PrintOut("Initial Order: ", mcArr); // Print the initial array.
Array.Sort(mcArr); // Sort the array.
PrintOut("Sorted Order: ", mcArr); // Print the sorted array.
ReadKey();
}
}
}
输出结果为;
Initial Order: 20 4 16 9 2
Sorted Order: 2 4 9 16 20
注意:如果仅仅声明CompareTo方法是不够的, 必须实现接口,也就是把接口名称放在基类列表中。
声明接口 (272P)
使用关键字 interface 来定义接口,语法为:
interface myInterface
{
//interface members
}
接口声明不能包含以下成员:
- 数据成员
- 静态成员
- 常量
- 析构和构造函数
接口声明只能包含如下类型的非静态成员函数的声明:
- 方法
- 属性
- 事件
- 索引器
- 这些函数成员的声明不能包含任何实现代码, 而在每一个成员声明的主体后必须使用分号。
- 按照惯例,接口名称必须从大写的I开始(比如ISaveable )。
- 与类和结构一样,接口声明还可以分隔成分部接口声明。
- 在默认情况下, 接口是内部的(internal)—— 即只有当程序集中的代码能够访问。 可以使用关键字 internal 写在 interface 的前