覆盖可变函数
Override variadic function
我无法覆盖可变函数。例子胜于雄辩,让我们举个例子:
这是我的摘要class:
public abstract class MyClass<T> {
public abstract T DoSomething(params Object[] objs);
public void ShowSomething(List<T> items){
foreach(T it in items){
Console.WriteLine(string.Format("{0},{1},{2}",it.propA,it.propB,it.propC));
}
}
// Other things
}
这是我试图覆盖它的尝试:
public class MyOverridenClass : MyClass<MyType> {
public override MyType DoSomething(int a, int b, string c){
return new MyType(){ propA = a+b, propB = a-b, propC = c+""+a};
}
}
从我的主要 :
public static void Main(string[] args){
MyOverridenClass cl = new MyOverridenClass();
List<MyType> lst = new List<MyType>();
lst.Add(cl.DoSomething(1,2,"foo"));
cl.ShowSomething();
}
我希望它输出:
3,-1,foo1
但是当我编译时,我有一个错误说没有找到合适的方法来覆盖 DoSomething(int, int, string)。
是否有可能,或者我是否必须找到解决方法?
谢谢!
重写方法时,签名必须相同。你不能"invent"一个新的签名。
public override MyType DoSomething(params Object[] objs)
{
// do something
}
在这里你无能为力...
所以你必须决定你想要你的方法有什么签名,并使用它。您甚至可以将两个签名都保留在 MyClass<T>
DoSomething
in MyOverriddenClass
不能覆盖 DoSomething(params Object[] objs)
因为你不能用非可变参数覆盖可变参数函数。
为什么不这样做的简单答案是因为规范是这样说的。但是在非 C# 的想象语言中,这仍然行不通,因为实现方法不如基方法具体,违反了约定。
在 C# 中,覆盖时签名必须完全匹配,但这不是正确性所必需的。为了正确性,一个方法实现契约就足够了。
例如,这是一个基 class,return 是一个 Base 类型的东西,并以一个对象作为参数。
public class Base {
public Base example(TParam obj)
}
如果我们要覆盖示例,我们需要它更具体才能正确
public class Derived : Base {
override public TReturn example(TParam2 obj) //this is illegal in C#
}
C# 要求 TReturn
== Base
和 TParam
== TParam2
。同时,正确性要求不那么严格。它只需要TReturn : Base
,TParam : TParam2
(注意它们是翻转的)
举个例子看看为什么
Base b = new Derived()
Base newbase = d.example(default(TParam))
它必须 return 一个在 Base
中 "fit" 的值。它也最多接受可以提供给 Base.example
的任何参数。如果它需要更具体的参数,那么你就被淘汰了,因为编译器不知道(并且不能知道并且不应该知道)b
是输入 Derived
.
现在回到可变参数方法。可以想象,某些不是 C# 但看起来有点像的语言确实允许这样做。可以想象,这种不是 C# 的语言具有一些语法糖来分解可变参数方法,并且可以来回转换以下内容:
public T Example(params object[] objs)
public T Example2(object obj1, object obj2)
但是派生类型中的实现在其参数列表中应该始终不那么具体,而不是更具体。因此,这种(非 C#)语言所能做的最好的事情就是允许您覆盖,例如,
public T Example(params SpecificType[] values)
和
public T Example(params object[] objs)
或
public T Example2(object obj1, object obj2)
但绝不会反过来。
tl;博士:
语言不允许,也不允许这样做,因为它会破坏替换原则。
我无法覆盖可变函数。例子胜于雄辩,让我们举个例子:
这是我的摘要class:
public abstract class MyClass<T> {
public abstract T DoSomething(params Object[] objs);
public void ShowSomething(List<T> items){
foreach(T it in items){
Console.WriteLine(string.Format("{0},{1},{2}",it.propA,it.propB,it.propC));
}
}
// Other things
}
这是我试图覆盖它的尝试:
public class MyOverridenClass : MyClass<MyType> {
public override MyType DoSomething(int a, int b, string c){
return new MyType(){ propA = a+b, propB = a-b, propC = c+""+a};
}
}
从我的主要 :
public static void Main(string[] args){
MyOverridenClass cl = new MyOverridenClass();
List<MyType> lst = new List<MyType>();
lst.Add(cl.DoSomething(1,2,"foo"));
cl.ShowSomething();
}
我希望它输出:
3,-1,foo1
但是当我编译时,我有一个错误说没有找到合适的方法来覆盖 DoSomething(int, int, string)。
是否有可能,或者我是否必须找到解决方法?
谢谢!
重写方法时,签名必须相同。你不能"invent"一个新的签名。
public override MyType DoSomething(params Object[] objs)
{
// do something
}
在这里你无能为力...
所以你必须决定你想要你的方法有什么签名,并使用它。您甚至可以将两个签名都保留在 MyClass<T>
DoSomething
in MyOverriddenClass
不能覆盖 DoSomething(params Object[] objs)
因为你不能用非可变参数覆盖可变参数函数。
为什么不这样做的简单答案是因为规范是这样说的。但是在非 C# 的想象语言中,这仍然行不通,因为实现方法不如基方法具体,违反了约定。
在 C# 中,覆盖时签名必须完全匹配,但这不是正确性所必需的。为了正确性,一个方法实现契约就足够了。
例如,这是一个基 class,return 是一个 Base 类型的东西,并以一个对象作为参数。
public class Base {
public Base example(TParam obj)
}
如果我们要覆盖示例,我们需要它更具体才能正确
public class Derived : Base {
override public TReturn example(TParam2 obj) //this is illegal in C#
}
C# 要求 TReturn
== Base
和 TParam
== TParam2
。同时,正确性要求不那么严格。它只需要TReturn : Base
,TParam : TParam2
(注意它们是翻转的)
举个例子看看为什么
Base b = new Derived()
Base newbase = d.example(default(TParam))
它必须 return 一个在 Base
中 "fit" 的值。它也最多接受可以提供给 Base.example
的任何参数。如果它需要更具体的参数,那么你就被淘汰了,因为编译器不知道(并且不能知道并且不应该知道)b
是输入 Derived
.
现在回到可变参数方法。可以想象,某些不是 C# 但看起来有点像的语言确实允许这样做。可以想象,这种不是 C# 的语言具有一些语法糖来分解可变参数方法,并且可以来回转换以下内容:
public T Example(params object[] objs)
public T Example2(object obj1, object obj2)
但是派生类型中的实现在其参数列表中应该始终不那么具体,而不是更具体。因此,这种(非 C#)语言所能做的最好的事情就是允许您覆盖,例如,
public T Example(params SpecificType[] values)
和
public T Example(params object[] objs)
或
public T Example2(object obj1, object obj2)
但绝不会反过来。
tl;博士:
语言不允许,也不允许这样做,因为它会破坏替换原则。