我们说我的界面如下。
interface CardHolder : IEnumerable<Card>
{
/// <summary> ...
void PutCard(Card card);
/// <summary> ...
void PutCards(Card[] card);
/// Some more methods...
}
我按如下方式实施。
public class ArrayCardHolder : CardHolder
{
private Card[] _cards;
private int _size = 0;
public ArrayCardHolder(int capacity)
{
_cards = new Card[capacity];
}
public void PutCard(Card card)
{
if (IsFull())
throw new Exception("This CardHolder is full. Capacity: " + Capacity());
_cards[_size++] = card;
}
public void PutCards(Card[] cards)
{
if (_size + cards.Length > _cards.Length)
throw new Exception("Adding the Cards would exceed this CardHolder its capacity. Capacity: " + Capacity());
for (int index = 0; index < cards.Length; index++)
_cards[_size++] = cards[index];
}
public IEnumerator<Card> GetEnumerator()
{
for (int index = 0; index < _size; index++)
yield return _cards[index];
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
///More methods.
}
为什么我的override
无法使用ArrayCardHolder
关键字
(例如public void override PutCard(Card card) { ///implementation }
表示该方法实现(即覆盖)接口?在这种情况下,项目将拒绝构建。
为什么在覆盖ToString()
时会有效?从CompareTo(T t)
实施IComparable<T>
后,为什么它不起作用?
我应该使用什么?我担心界面中的文档不适用于我的实现方法。使用@Override
注释时,Java就是这种情况。
答案 0 :(得分:8)
接口的方法不是覆盖,它们是实现的。您对抽象/虚拟方法感到困惑,可以覆盖它。
示例:
public interface IFoo
{
void DoA();
}
public abstract class BaseFoo : IFoo
{
public void DoA() { } // *this HAS to be implemented*
public virtual void DoB() { }
}
public abstract class MyFoo : BaseFoo
{
// *this CAN be implemented, which would override the default implementation*
public override void DoB() { }
}
正如其他人所提到的,ToString
是基类virtual
的{{1}}方法,这就是覆盖的原因。
答案 1 :(得分:2)
如果标记为虚拟,则可以覆盖任何基本类型的方法。例如,您可以覆盖ToString()方法,因为它在对象类中标记为虚拟。而object是.Net中的基类型。
Html.DropDownListFor
实现接口是因为它们完成了任何实现,因此没有什么可以覆盖。例如,IComparable是一个使用CompateTo()方法的接口,它没有实现,因此您在继承此接口的类中实现它。
public override string ToString()
{
return base.ToString();
}
我希望我说清楚。
答案 2 :(得分:1)
“界面”是描述“某些特定编程事物面向公众的面孔必须是什么样的。”
该接口的任何“具体实现”必须(至少)执行接口所要求的所有内容。 (它如何“完成”完全取决于实现者。)
现在,让我们说你有两个类Dad
和Teenager
,两个implement
同一个界面。但Teenager
(虽然显然是Dad
的后代)想要做一个这些事情......比如,play_music
......有点不同。 Teenager
可以覆盖 Dad
的方法。
只要Teenager
的实施继续符合界面的限制,我们的青少年就可以像他喜欢的那样大声播放他的音乐。
答案 3 :(得分:0)
您不是重写方法,而是实现接口的成员。
在C#中,仅在覆盖现有实现时使用覆盖。一个例子是ToString()。您覆盖的方法必须在基类上标记为 virtual 。
答案 4 :(得分:0)
.ToString
是基类Object
中的虚方法。这就是你可以覆盖它的原因。但是你没有覆盖接口方法,你实现它。
如果要提供默认实现并可能在类中覆盖它,则需要使用带有虚方法的基类。所以:
接口方法:您必须在类中提供实现。
抽象方法:您必须在派生类中提供实现。
虚方法:您可以在派生类中提供实现或保留默认实现。 (或通过调用base.MethodName();
混合然后提供其他代码)
示例:强>
public interface IContract
{
// It is a must to implement this method in classes
void MustImplement();
}
public abstract class BaseClass
{
// Just signature, No implementation. It is a must to implement.
public abstract void IAmAbstract();
public virtual void IAmVirtual()
{
Console.WriteLine("I provide default implementation");
}
}
public class DerivedClass : BaseClass, IContract
{
public override void IAmAbstract()
{
Console.WriteLine("provides Abstract Method implementation In Derived Class");
}
// It is optional to override this method
public override void IAmVirtual()
{
// class default implementation
base.IAmVirtual();
Console.WriteLine("provides Additional virtual Method implementation In Derived Class");
}
public void MustImplement()
{
Console.WriteLine("provides Interface Method implementation In Derived Class");
}
}
答案 5 :(得分:0)
如前所述,重写适用于虚拟方法和抽象方法的实现,而不适用于接口方法的实现。
所有这些令人讨厌的事情是,当用于实现接口方法的方法变得孤立时,无法生成警告。
有趣的是,java工具提供了一个选项,允许在接口方法上使用@override,以便在接口方法变得孤立时会生成错误/警告。
从语言实现的角度来看,问题是接口方法的替代是否是虚拟的。我认为“替代虚拟”将是一个选择。或“替代摘要”。
https://github.com/dotnet/csharplang/issues/3510
因此,从技术上讲,对“为什么”的答案不是“因为你做不到”,而是更深刻,更险恶的事情;即:因为C#语言规范错误。只是说。 :-P