在C#中,假设类C1实现接口I1,类C2从C1派生。
同样的问题,如果在C1的声明中,I1有一个类型参数, C1和C2的类型参数不同?
例如,
public abstract class C1: I1<C1>
public class C2: C1, I1<C2>
我是否需要在C2的定义中编写I1?
感谢。
答案 0 :(得分:4)
IEnumerable<int>
是一个完全不同的类型而不是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()
必须为implemented explicitly,否则会与基类冲突。 int
版本。具有相同名称的方法不允许仅的返回类型不同。
答案 1 :(得分:1)
如果基类实现了某个接口,则不必在派生类中重新实现它。
答案 2 :(得分: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!" !!!
您的问题可能是指Foo
和DerivedFoo
但该语言的一个很少已知的功能是AnotherDerivedFoo
,您基本上会以不同的行为重新实现该界面。
请注意以下内容:
var anotherDerivedFoo = new AnotherDerivedFoo(); //reference is typed AnotherDerivedFoo
Console.WriteLine(anotherDerivedFoo.SayHello()); //prints "Foo says hello!"
这是因为您无法重新实现接口的隐式实现。
是的,您必须同时申报。请注意,现在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)!
所以要小心!