乡亲
我碰到很多线程来理解多态性(编译时和运行时)。 我很惊讶地看到一些链接,其中程序员都声称是超载运行和压倒一切的是编译时间。
我想从这里知道的是:
- 运行时多态性与实时例如,小码和什么情况下,我们应该使用。
- 编译具有实时例如,小码和时间多态性时使用。
因为我看了很多的理论定义,但我不理解的是满意的。
另外,我给了一个念头,那地方我也感觉到了,超载应该是运行时间为,因为,说我有一个计算面积,在运行时的方法只有它决定哪个重载的方法调用基于我传递参数(说,如果我只能传递一个参数,它应该火广场,如果参数为2,它应该火矩形)......所以是不是我可以声称它的运行? 如何其complie时间? (大多数理论上说,超载编译时间,但他们甚至不给一个正确的实时例子......很少有权利要求其运行时)....
另外,我觉得首要的是编译时间,因为,当你写代码和complie,你确保你使用虚拟的关键字,并覆盖在派生类的方法,否则会给你编译时错误。 所以我觉得它的编译时间,在那里我在一个线程中看到了同样的方式.....但多数线程声称其运行时:d
我很困惑:(这个问题是附加到我的问题1和2,请用实时例如帮助..因为我已经知道的理论定义.... :(
谢谢....
在超载的情况下,使用静态(编译时)多态性,因为编译器是准确地知道你调用哪个方法。 例如:
public static class test
{
static void Main(string[] args)
{
Foo();
Foo("test");
}
public static void Foo()
{
Console.WriteLine("No message supplied");
}
public static void Foo(string message)
{
Console.WriteLine(message);
}
}
在这种情况下,编译器知道正是我们是基于数目/类型的参数调用,这美孚()方法。
重写是动态的(运行时)多态性的一个例子)。 这是由于编译器并不一定知道在编译时间被传递什么类型的对象。 假设你有一个库中的以下类别:
public static class MessagePrinter
{
public static void PrintMessage(IMessage message)
{
Console.WriteLine(message.GetMessage());
}
}
public interface IMessage
{
public string GetMessage();
}
public class XMLMessage : IMessage
{
public string GetMessage()
{
return "This is an XML Message";
}
}
public class SOAPMessage : IMessage
{
public string GetMessage()
{
return "This is a SOAP Message";
}
}
在编译的时候,你不知道,如果函数的调用者传递一个XMLMessage之外,SOAPMessage,或可能在其他地方定义的另一种类型的消息对象的。 当PrintMessage()函数是呼叫时,它确定在运行时要使用哪个的GetMessage()的版本,基于被传入消息对象的类型。
阅读: 多态性(C#编程指南)
类似的答案: 编译时和运行时多态性
那么,有两种类型的多态性作为陈述如下:
静态多态(早期绑定):
静态多态也被称为早期绑定和编译时多态性。 方法重载和运算符重载是相同的例子。
这是被称为早期绑定,因为编译器知道具有相同名称以及还有重载函数被调用砥在编译时已知的功能。
例如:
public class Test
{
public Test()
{
}
public int add(int no1, int no2)
{
}
public int add(int no1, int no2, int no3)
{
}
}
class Program
{
static void Main(string[] args)
{
Test tst = new Test();
int sum = tst.add(10, 20);
// here in above statement compiler is aware at compile time that need to call function add(int no1, int no2), hence it is called early binding and it is fixed so called static binding.
}
}
动态多态性(后期绑定):
public class Animal
{
public virtual void MakeSound()
{
Console.WriteLine("Animal sound");
}
}
public class Dog:Animal
{
public override void MakeSound()
{
Console.WriteLine("Dog sound");
}
}
class Program
{
static void Main(string[] args)
{
Animal an = new Dog();
an.MakeSound();
Console.ReadLine();
}
}
如在上面的代码,因为任何其它的呼叫到一个虚拟方法,将被编译到一个callvirt IL指令。 这意味着,被称为在运行时确定(除非JIT可以优化某些特殊的情况下),但是编译器检查,该方法存在的实际方法,它选择了最合适的过载(如果有的话),并有保证该函数指针将在该类型的虚函数表明确限定的位置中存在(尽管这是一个实现细节)。 解决虚拟呼叫的过程是非常快(只需提领几个指针),所以它并没有太大的差别。
public class Animal {
public virtual void MakeSound()
{
Console.WriteLine("Animal sound");
} }
public class Dog:Animal {
public override void MakeSound()
{
Console.WriteLine("Dog sound");
} }
class Program {
static void Main(string[] args)
{
Animal an = new Dog();
an.MakeSound();
Console.ReadLine();
} }
这是动态的多态性,因为它在运行时其MakeSound的版本将被调用的父母或孩子的任何决定,作为一个孩子可能无法覆盖父功能或可能覆盖它,但是这一切都在运行时,该版本决定叫做 ....