多继承(multiple inheritance)是指一个类从两个或多个基类派生的能力。
CLR不支持多继承,CLR只是通过接口提供了“缩水版”的多继承。
实现接口的类或结构必须实现接口定义中指定的接口成员。
interface IEquatable<T>
{
bool Equals(T obj);
}
实现IEquatable<T>接口的任何类或结构都必须包含与该接口指定的签名匹配的Equals方法的定义。
public class Car : IEquatable<Car>
{
public string Make { get; set; }
public string Model { get; set; }
public string Year { get; set; }
public bool Equals(Car car)
{
if (this.Make == car.Make && this.Model == car.Model && this.Year == car.Year)
{
return true;
}
else
{
return false;
}
}
}
IEquatable<T>的定义不为Equals提供实现,该接口仅定义签名。
类或结构可以实现多个接口,但是类只能继承单个类(抽象或不抽象)。
接口可以包含方法、属性、事件、索引器或这四种成员类型的任意组合。
接口成员会自动成为公共成员,不能包含任何访问修饰符。成员也不能是静态成员。
若要实现接口成员,实现类的对应成员必须是公共、非静态,并且具有与接口成员相同的名称和签名。
接口具有以下属性:
- 接口类似于抽象基类。实现接口的任何类或结构都必须实现其所有成员。
- 接口无法直接进行实例化。其成员由实现接口的任何类或结构来实现。
- 接口可以包含事件、索引器、方法和属性。
- 接口不包含方法的实现。
- 一个类或结构可以实现多个接口。一个类可以继承一个基类,还可实现一个或多个接口。
13.1类和接口继承
从Object派生任何类实际都继承了以下内容:
- 方法签名
- 方法的实现(ToString, Equals, GetHashCode, GetType)
13.2定义接口
接口对一组方法签名进行了统一命名。接口还能定义事件,无参属性和索引器。所有这些本质上都是方法。但接口不能定义构造器方法。接口也不能定义任何实例字段。
C#禁止接口定义任何一种这样的静态成员。
在C#中是用interface关键字定义接口的。要为接口指定一个名称和一组实例方法签名。
对CLR而言,接口定义就像是一个类型定义。也就是说,CLR会为接口类型对象定义一个内部数据结构,同时可用反射机制来查询接口类型的功能。
和类型一样,接口可用在文件范围内定义,也可嵌套在另一个类型中定义。定义接口类型时,可指定你希望的任何可视性/可访问性(public, protect, internal等)。
接口成员会自动成为公共成员,不能包含任何访问修饰符。成员也不能是静态成员。
根据约定,接口类型名称要以大写I开头,目的是方便在源代码中辨认接口类型。
CLR支持泛型接口和在接口中的泛型方法。
13.3继承接口
以下代码展示了如何定义一个实现该接口的类型:
public interface IComparable<in T>
{
//接口成员不能包含任何访问修饰符,不能是静态成员,它会自动成为公共成员
int CompareTo(T other);
}
public sealed class Point : IComparable<Point>
{
private Int32 m_x, m_y;
//接口不能定义构造器方法,实现接口的类可以定义构造器方法
public Point(Int32 x, Int32 y)
{
m_x = x;
m_y = y;
}
//和接口对应的成员必须是公共非静态的,和接口成员相同的名称和签名
public Int32 CompareTo(Point other)
{
return Math.Sign(Math.Sqrt(m_x * m_x + m_y * m_y)
- Math.Sqrt(other.m_x * other.m_x + other.m_y * other.m_y));
}
public override String ToString()
{
return String.Format("{0},{1}", m_x, m_y);
}
}
public static class Program
{
public static void Main()
{
Point[] points = new Point[] { new Point(3, 3), new Point(1, 2) };
if (points[0].CompareTo(points[1]) > 0)
{
Point tempPoint = points[0];
points[0] = points[1];
points[1] = tempPoint;
}
Console.WriteLine("Points from closest to (0,0) to farthest:");
foreach (Point p in points)
Console.WriteLine(p);
}
}
C#编译器要求将用于实现一个接口的方法标记为public。
编译器会将实现接口的方法标记为virtual和sealed。