簡體   English   中英

我是否需要在派生類的定義中指定由基類實現的接口?

[英]Do I need to specify interface implemented by a base class in the definition of a derived class?

在C#中,假設類C1實現接口I1,並且類C2從C1派生。

  1. 一般來說,在C2的定義中,是否需要聲明C2實現I1?
  2. 同樣的問題,如果在C1的聲明中,I1是否具有類型實參,並且該類型實參對於C1和C2是否不同?

    例如,

     public abstract class C1: I1<C1> public class C2: C1, I1<C2> 

    我需要在C2的定義中寫I1嗎?

謝謝。

  1. 否。如果接口是在基類中實現的,則派生類也將實現它們,而無需再次明確聲明。
  2. 必須顯式聲明不同通用參數的通用接口。 原因是,例如IEnumerable<int>是與IEnumerable<string> 完全不同的類型IEnumerable<string>最可能需要派生類實現具有與基類不同的簽名的方法。

例:

public interface IGenericInterface<T> 
{
     T GetSomething();
     void DoSomething(T arg);
}

public class BaseClass : IGenericInterface<int>
{
     public virtual int GetSomething() { return 5; }
     public virtual void DoSomething(int arg) { Console.WriteLine(arg); }
}

public class Derived : BaseClass, IGenericInterface<string>
{
     string IGenericInterface<string>.GetSomething() { return "hello world!"; }
     public void DoSomething(string arg) { Console.WriteLine(arg); }
}

請注意,在此示例中,需要顯式實現 Derived.GetSomething() ,因為否則它將與基類的int版本沖突。 具有相同名稱的方法不允許在返回類型上有所不同。

如果基類實現某些接口,則不必在派生類中重新實現它。

  1. 考慮到正常的用例,答案通常是“否”。 但是,在某些情況下,您應該再次聲明接口。 當您要修改行為時。 考慮以下代碼:

     public interface IHello { string SayHello(); } public class Foo : IHello { public string SayHello() => "Foo says hello!"; } public class DerivedFoo : Foo { } public class AnotherDerivedFoo : Foo, IHello { string IHello.SayHello() => "AnotherDerivedFoo says hello!"; } 

    現在:

     IHello foo = new Foo(); IHello derivedFoo = new DerivedFoo(); IHello anotherDerivedFoo = new AnotherDerivedFoo(); Console.WriteLine(foo.SayHello()); //prints "Foo says hello!" Console.WriteLine(derivedFoo.SayHello()); //prints "Foo says hello!" Console.WriteLine(anotherDerivedFoo.SayHello()); //prints "AnotherDerivedFoo says hello!" !!! 

    您的問題可能涉及FooDerivedFoo 但是該語言的一個鮮為人知的功能是AnotherDerivedFoo ,您可以在其中基本上以不同的行為重新實現接口。

    但是請注意以下幾點:

     var anotherDerivedFoo = new AnotherDerivedFoo(); //reference is typed AnotherDerivedFoo Console.WriteLine(anotherDerivedFoo.SayHello()); //prints "Foo says hello!" 

    這是由於您無法重新實現接口的隱式實現。

  2. 是的,您必須同時聲明兩者。 請注意,雖然,現在C2同時實現I1<C1>I1<C2>一個不取消其他的,他們是,所有的目的,兩個不同的接口。

    這可能會導致不幸的情況:

     public interface I1<T> { string Foo(T fooable); } public class C1: I1<int> { public string Foo(int i) => "C1.Foo called"; } public class C2: C1, I1<double> { public string Foo(double d) => "C2.Foo called"; } 

    現在:

     var c2 = new C2(); Console.WriteLine(c2.Foo(1)); //C2.Foo(double d) is called, //not C1.Foo(int i)! 

    所以要小心!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM