如果我有一个类SubOfParent,它是Parent的子类,还有两个方法:
public static void doStuff(Parent in) {}
public static void doStuff(SubOfPArent in) {}
为什么在传递SubOfParent类型对象时会调用 first doStuff?
感谢您对此有任何见解!
答案 0 :(得分:12)
Parent p = new SubOfParent();
SubOfParent s = new SubOfParent();
doStuff(p); //calls doStuff(Parent in)
doStuff(s); //calls doStuff(SubOfParent in)
//If you're working with a parent but need to call the subclass, you need to upcast it.
dostuff(p as SubOfParent);
答案 1 :(得分:8)
方法重载是在编译时完成的,而不是在运行时完成的,所以你不会看到任何多态性。无论调用代码知道什么类型,都将指定调用哪个方法。
如果要调用第二种方法,可以转换为SubOfPArent
类型,或者可以将这些方法放入类中,然后调用它来获取多态性:
public class Parent
{
public virtual void doStuff() {}
}
public class SubOfPArent : Parent
{
public override void doStuff() {}
}
...
Parent obj = getASubOfPArent();
obj.doStuff();
答案 2 :(得分:4)
您可能使用Parent
类型的变量调用该方法。
由于在编译时解析了方法重载,编译器只能根据参数的静态编译时类型选择重载。
因此,即使您的变量在运行时实际上可能包含SubOfParent
实例,编译器也不会知道,因此会选择第一个重载。
相反,虚拟方法在运行时根据所涉及实例的实际类型进行解析
因此,如果SubOfParent
重写了一个虚方法,则在Parent
类型的变量上调用该方法将正确调用重写方法(如果该实例实际上是SubOfParent
类型。
答案 3 :(得分:2)
我认为您在代码中转换为Parent
,或以其他方式提供Parent
类型。所以我认为行为是正确的,你期望发生的是不正确的。
两个重载对SubOfParent
引用都有效是正确的,但重载决策逻辑会查找更具体的方法,因此应该找到最具体的重载。
SubOfParent p = new SubOfParent();
doStuff((Parent)p); // Calls base overload
doStuff(p); // Calls specific overload
答案 4 :(得分:2)
如果您对使用dynamic
关键字感到满意,可以考虑这样做:
private static void doStuffImpl(Parent obj) {
Console.WriteLine("I'm a Parent!");
}
private static void doStuffImpl(SubOfParent obj) {
Console.WriteLine("I'm a Sub of Parent!");
}
public static void doStuff(Parent obj) {
try {
doStuffImpl(obj as dynamic);
}
catch (RuntimeBinderException ex) {
// Not implemented !
}
}
如果你有很多子类,它会很有用。
doStuffImpl(obj as dynamic);
将在运行时进行评估。 doStuffImpl
将使用obj
的真实类型进行调用。
答案 5 :(得分:1)
方法重载在编译时完成,因此在编译时依赖于静态类型来确定重载方法。在您的示例中,可能会发生以下情况:
public static void Main(string[] args)
{
SubOfParent a = new SubOfParent();
doStuff(a); // doStuff(SubOfParent) is called
}
编译时的静态类型是SubOfParent,因此将调用预期的重载。
public static void Main(string[] args)
{
Parent a = new SubOfParent();
doStuff(a); // doStuff(Parent) is called
}
静态类型(声明类型)是Parent。在这种情况下,无论a.GetType()在运行时返回的值如何,都将选择其他重载版本。
答案 6 :(得分:0)
要调用doStuff(SubOfPArent),你需要这样的东西:
SubOfPArent.doStuff(new SubOfPArent());
但我认为你直到运行时才知道类型吗?
Tster说的更优雅。我认为这是正确的。
答案 7 :(得分:0)
基本上,编译器根据该对象的声明的类型解析在对象上调用的方法(即,当该对象作为参数传递时)。因此,如果您将变量键入为Parent
并将其传递给doStuff
,则编译器会将该方法调用解析为带有Parent
的重载,即使在运行时该对象变为成为SubOfParent
。
方法通过对象调用(即类的实例方法)在运行时表现出多态性:执行的方法基于对象的实际类型。
所以,如果你有这个:
class Parent
{
public virtual void doStuff() { }
}
class SubOfParent : Parent
{
public override void doStuff() { }
}
Parent p = new SubOfParent();
p.doStuff();
然后代码可以按预期工作。
答案 8 :(得分:0)
你可以重载功能 通过声明具有相同名称和不同参数的多个函数