接口是C#的一个功能,我从来没有完全看到它的目的。我看到他们一直用在专业代码中,但对于我的生活,我无法解决这个问题。
我的问题是关于模拟多重继承的接口。在阅读这个主题时,我经常会出现这样的例子:
interface IAddition
{
int add(int a, int b);
}
interface ISubtraction
{
int sub(int a, int b);
}
class Calculation : IAddition, ISubtraction
{
public int add(int a, int b)
{
return result1 = a + b;
}
public int sub(int a, int b)
{
return result1 = a - b;
}
}
我不明白的是 - 界面带来了什么好处?它看起来像你可以完全删除它们,并且Calculation类仍然可以完全相同。我在这里错过了什么?
任何帮助都将受到赞赏 - 我一直在寻找一些东西来制作界面'点击'在我脑海里已经有一段时间了。
值得注意的是我是游戏开发者,我正在为此寻找解决方案,以提高我开发游戏的能力,但我认为这是一个足够普遍的问题。这里。
答案 0 :(得分:2)
是的,你是对的。删除接口后,代码仍将编译。那么为什么要添加它们呢?
嗯,您的IAddition
和ISubtraction
示例并不是很好。由于学习编程的最佳方式是查看其他人如何编码,我将使用System.IComparable<T>
接口作为示例。它是.NET框架提供的接口。
我们使用接口的原因是实现多态。接口就像类必须符合的协议。如果一个类实现了一个接口,那么可以保证该类可以执行接口指定的操作。这听起来很混乱所以让我们来看看IComparable<T>
界面。为了使事情更简单,让它成为IComparable<int>
IComparable<int>
有这种方法:
int CompareTo(int other);
这基本上意味着
实现
IComparable<int>
的所有内容都具有与整数进行比较的能力。我们可以调用其CompareTo
方法来确定它是否大于,等于或小于任何int
。
由于实现IComparable<int>
的所有内容都必须包含方法CompareTo
,因此可以保证您调用CompareTo
的对象可以与int
进行比较。< / p>
那么这有用吗?
排序数组时,与其他内容进行比较的功能非常有用。 Array.Sort
方法使用IComparable<T>
接口。以下是Sort
方法的工作原理(高度简化):
首先检查是否可以通过检查它们是否实现IComparable<T>
来比较数组的元素。如果他们这样做,请通过致电CompareTo
来比较它们!为什么可以确定有一个名为CompareTo
的方法?因为这些对象都实现了IComparable<T>
,这保证了CompareTo
方法!比较后,Sort
可以确定哪个元素是第一个也是最后一个。
你看到不同的东西需要以不同的方式进行比较吗?可以通过从另一个中减去一个并检查结果是正数还是负数来比较整数和double
s。但字符串按字母顺序进行比较。如果没有IComparable<T>
界面,则会有针对字符串的Sort
方法,Sort
的{{1}}方法以及int
可以比较的所有类型的方法。更糟糕的是,如果客户端代码创建了可以比较的东西,客户端代码需要编写自己的Sort
方法!不要忘记,还有很多其他方法可以利用比较的能力。所有那些方法是否需要为每种类型使用不同的版本?
这就是界面如此重要的原因。有了它们,只需要一个Sort
方法,因为多态性可以处理其余的问题。
让我总结一下接口的优点:
Sort
方法!)我们假设Sort
不存在,IComparable<T>
和string
以及可以作为自己的int
方法进行比较的其他类型。 CompareTo
方法可能如下所示
Sort
你可以争辩说,一个public static void Sort(int[] arr) {
// note that I'm using bubble sort here. A real sort method wouldn't use this coz it's slow.
// source: http://stackoverflow.com/questions/14768010/simple-bubble-sort-c-sharp
int temp = 0;
for (int write = 0; write < arr.Length; write++) {
for (int sort = 0; sort < arr.Length - 1; sort++) {
if (arr[sort].CompareTo(arr[sort + 1]) > 0) {
temp = arr[sort + 1];
arr[sort + 1] = arr[sort];
arr[sort] = temp;
}
}
}
}
public static void Sort(string[] arr) {
string temp = 0;
for (int write = 0; write < arr.Length; write++) {
for (int sort = 0; sort < arr.Length - 1; sort++) {
if (arr[sort].CompareTo(arr[sort + 1]) > 0) {
temp = arr[sort + 1];
arr[sort + 1] = arr[sort];
arr[sort] = temp;
}
}
}
}
方法需要Sort
检查每个元素的类型也可以。是的,但是它遇到了与多个object[]
方法相同的问题。如果创建了一个新的可比较类,您仍需要添加另一个排序方法或另一个检查。
如果您有Sort
界面,问题就会结束!
IComparable<T>
由于类型约束表明public static void Sort<T>(T[] arr) where T : IComparable<T> {
T temp;
for (int write = 0; write < arr.Length; write++) {
for (int sort = 0; sort < arr.Length - 1; sort++) {
if (arr[sort].CompareTo(arr[sort + 1]) > 0) {
temp = arr[sort + 1];
arr[sort + 1] = arr[sort];
arr[sort] = temp;
}
}
}
}
必须实现T
,因此可以在数组中的每个对象上调用IComparable<T>
而不会出现任何问题!
现在,如果您希望添加另一个类似的类,您需要做的就是实现该接口。如果界面不存在,则必须编写CompareTo
方法和 CompareTo
方法!
答案 1 :(得分:1)
See this msdn article for details ("No Multiple-Inheritance in .NET" section):
接口解决了多重继承的问题,在尝试查找正确的实现时,不允许在编译器中防止歧义。在他们的示例中,BabyBasset继承了Hound和Puppy,但是说这两个类都提供了一个名为“Bark()”的方法的实现,哪一个会被执行?因此含糊不清。
类可以实现多个接口,并且在存在歧义的情况下(即,具有相同名称的单独接口中的两个方法),可以在类中显式实现它们,从而消除歧义。
答案 2 :(得分:0)
接口是一个合约,对象将拥有某些提供特定功能的成员。
这允许您提供一个抽象级别,以便可以编写代码以使用接口而不是类。
例如,我可能有一个继承IList接口的类。可以有任意数量的实现只是存储“事物”列表。在幕后,对我而言,实现是什么并不重要,我可能关心的是它们包括Add()
和GetEnumerator()
所以我可以添加内容并循环它们。由继承接口的类的实现者来提供实现。
通常会进行多重继承,以便您可以拆分功能。您可能有一个进行减法,加法或两者的类。调用继承添加接口的对象上的方法的代码不关心除提供附加功能的成员之外的任何内容。与使用继承减法接口的类的代码相同。然后,它允许您或其他人用其他东西替换这些类,只要它们实现消费者不关心的界面。
答案 3 :(得分:0)
接口基本上是您和您的客户之间的契约,就像强制执行一样,它强制您的客户端必须实现接口中声明的方法。
让我们以您的代码为例。
interface IAddition
{
int add(int a, int b);
}
interface ISubtraction
{
int sub(int a, int b);
}
class Calculation : IAddition, ISubtraction
{
}
所以如果你不实现Add
和Sub
方法,编译器会给你错误。如果你删除你的接口,没有合同,所以noboday检查你的类实现。你做任何你想做的事。
允许多重继承,它在多种情况下具有重要意义。你的类可以与其他接口有多个合同。示例您有1个接口,10个不同的接口正在实现此接口。因此,一些类可以实现最顶层的接口,否则一些可以实现1,2,5接口,具体取决于它们各自的功能。
答案 4 :(得分:0)
接口是一种绑定合同,可以保证您的类实现某些功能。一个类使用的接口越多,广告使用的功能就越多。
想想谷物盒标签等界面。如果它说“没有添加糖”,你可以相当肯定你的麦片(或你的班级)没有添加任何糖。
在您的示例中IAdd
和ISub
正在宣传您的班级知道如何执行某些操作。由您来决定您希望将类的功能拆分到一个或多个接口中的细粒度级别。这一切都取决于未来的用途。如果你有一个仅由一个类使用的接口,那么可能并不真正需要该接口。