2012-06-06 57 views
13

民间重载是如何编译时间和覆盖是运行时?

我遇到了很多理解多态性(编译时间和运行时间)的线程。我很惊讶地看到一些程序员声称Overloading是Runtime和Overriding是编译时的链接。

我想从这里知道的是:

  1. 运行时多态性与实时例如,小码和什么情况下,我们应该使用。
  2. 使用REAL TIME示例和小代码编译时间多态性以及何时使用。

因为我看过很多理论的定义,但我不理解的是满意的。

另外,我给了一个想法,我也觉得,重载应该是运行时,因为,比如说我有一个计算Area的方法,在运行时它只能根据参数I pass来决定调用哪个重载方法如果我只传递一个参数,它应该触发Square,如果参数是2,它应该触发Rectangle)....那么是不是我可以声明它的运行时?它的编译时间如何? (大多数理论上讲,过载是编译时间,但他们甚至没有给出一个正确的实时时间的例子...很少声称它的运行时间)...

此外,我觉得重写是编译时,因为,当你编写代码并且complie,你确保你使用了virtual关键字,并且在派生类中重写了这个方法,否则会给你编译时错误。所以我觉得它的编译时间,以同样的方式,我在一个线程看到.....但多数线程声称其运行时:d

我很困惑:(这个问题是附加到我的问题1和2,请与实时例如帮助..因为我已经知道的理论定义.... :(

谢谢....

+0

如果我完全理解你的问题:运行时间,调用虚拟方法。编译时间,调用任何其他方法。 –

+0

UhmmM杰夫,但它是一切吗? – Learner

回答

11

在重载的情况下,您使用的是静态(编译时)多态性,因为编译器知道您正在调用哪种方法。例如:

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); 
    } 
} 

在这种情况下,编译器根据参数的数量/类型确切知道我们调用的是哪个Foo()方法。

覆盖是一个动态(运行时)多态性的例子)。这是由于编译器不一定知道在编译时传入什么类型的对象。假设你有下面的类在库:

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()的版本,基于被传入消息对象的类型。

+3

乔恩,我应该和你这样的人一起工作,为了两件事情:1.为了完成任务而为实时和令人满意地学习东西,为了激情而不是编码并获得报酬2.你的分享你的知识的态度,最重要的是能够提问人的思维方式......与MSDN不同...... :(非常感谢Jon,你的榜样我理解它更大程度上的概念....开心:)干杯 – Learner

+0

只是为了避免出现“Foo”的问题:无法在静态类中声明实例成员,你的方法必须是静态的。 – Rahul

+0

我花了一分钟才明白你的意思,但我看到你指的是你的编辑。感谢您指出我在第一个示例中声明了静态类中的实例成员。我匆匆把这个例子扔在一起,没有注意到。 –

3

阅读:Polymorphism (C# Programming Guide)

类似的答案:Compile Time and run time Polymorphism

那么,有两种类型多态性的规定如下:

  • 静态多态(早期绑定)
  • 动态多态性(后期绑定)

静态多态(早期绑定):

静态多态也知道作为早期绑定和编译时间多态性。方法重载和运算符重载是相同的例子。

这是被称为早期绑定,因为编译器知道具有相同名称的功能也发生过载功能砥称为是在编译时已知。

例如:

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可以优化某些特殊情况),但编译器检查该方法是否存在,是否选择了最合适的重载(如果有的话),并且它有保证函数指针将存在于类型的vtable中的一个定义良好的位置(即使这是一个实现细节)。解决虚拟呼叫的过程非常快(您只需要解除引用几个指针),所以它没有太大区别。

+0

Pranay谢谢你。但为什么只有当我在运行时输入值时,在你的情况下只说2个参数,它决定用2个参数调用该方法?它只是在编译时编译......你怎样称它为编译时间:(它的运行时间,因为在运行时只基于输入,它会触发相应的功能...... – Learner

+0

@Divine-它的命令时间因为编译器知道它必须调用哪个方法,例如,如果2参数在那里,编译器很容易检测到它必须调用2参数方法...如果3比调用gose参数到3参数... –

+0

@ Divine-编译器知道签名这样可以很容易地解决问题...... –

0
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将被称为父代或子代,因为子代可能不会覆盖父代函数或可能覆盖它,但所有这些都是在运行时决定的,哪个版本被称为....