编译时间多态性与运行时多态性

时间:2010-01-28 07:06:02

标签: c# oop

为什么重载在C#中称为编译时多态并覆盖运行时多态?

10 个答案:

答案 0 :(得分:33)

嗯,重载决策(使用哪种方法签名,基于参数 1 )由编译器完成,而覆盖决策(哪种方法实现在执行时由CLR根据方法的目标类型使用

我通常不会调用重载“多态”。根据我的经验,这个词通常是指的是覆盖。我认为重载确实允许你将一种类型的对象视为另一种类型,尽管不需要在那里超载本身 - 这只是正常的类型转换。

这是一个示例,显示在编译时执行重载选择:

using System;

class Test
{
    static void Foo(object a)
    {
        Console.WriteLine("Object overload called");
    }

    static void Foo(string a)
    {
        Console.WriteLine("String overload called");
    }

    static void Main()
    {
        object x = "hello";
        Foo(x);
    }
}

这里调用了Foo(object)重载,因为x在编译时的类型为object - 它只是在执行时才知道它引用了一个字符串。

将此与此示例进行比较:

using System;

class Base
{
    public virtual void Foo()
    {
        Console.WriteLine("Base.Foo called");
    }
}

class Derived : Base
{
    public override void Foo()
    {
        Console.WriteLine("Derived.Foo called");
    }
}

class Test
{
    static void Main()
    {
        Base x = new Derived();
        x.Foo();
    }
}

此处x编译时类型为Base,但它仍然是派生类的重写方法,因为执行时< / em> x引用的对象的类型为Derived


1 由于方法隐藏等原因,它实际上稍微复杂一些 - 但在简单的情况下,您可以将其视为仅仅选择签名。

答案 1 :(得分:20)

重写函数是具有相同签名的函数,但是在不同的派生类中实现。在编译时,通常基类类型用于引用对象,但在运行时此对象可以是派生类型,因此当调用重写方法时,调用的实现取决于对象的类型执行在编译时未知的调用(基本类型与派生类型)。

重载(不是真正的多态)只是具有相同名称但签名不同的多个函数(想想一个对象使用不同数量的参数的多个构造函数)。调用哪个方法在编译时是已知的,因为此时指定了参数。

答案 2 :(得分:7)

多态性

通过继承,一个类可以用作多个类型;它可以用作自己的类型,任何基类型,或任何接口类型,如果它实现接口。这称为多态。

多态性意味着有多种形式。重载和重写用于实现多态性。多态性分为编译时多态或早期绑定或静态绑定和运行时多态或后期绑定或动态绑定。

覆盖 - 在类及其子类中具有相同参数和相同返回类型的相同方法名称。覆盖C#使用“override”关键字。覆盖方法意味着用新的数据处理方式替换它。

重载 - 具有不同参数的相同方法名称,可能是也可能不是同一类本身写入的返回类型。

编译时间多态性或早期绑定

编译器识别在编译时必须执行哪种多态形式的多态,称为编译时多态或早期绑定。

早期绑定的优点是执行速度很快。因为在编译期间编译器知道关于该方法的所有事情,所以自身和缺点是缺乏灵活性。

早期绑定的示例包括重载方法,重载运算符和使用派生对象直接调用的重写方法。

运行时多态或后期绑定

编译器识别在运行时而不是在编译时执行哪种多态形式的多态性称为运行时多态或后期绑定。

后期绑定的优点是灵活性和缺点是执行速度很慢,因为编译器必须获取有关在运行时执行的方法的信息。

后期绑定的示例是使用基类对象调用的重写方法。

 class A
 {
    public virtual void Leg(string Name)
    {

    }
 }

 class B:A
 {
    public override void Leg(string Name)
    {

    }
 }

过载的示例

 class A
 {
  void a()
   {
   }
  void a(string Name)
   {
   }
 }

换句话说,“单个物体的许多形式称为多态。”

例如:

团队负责人表现为Sub Ordinate。 团队负责人对他/她的老年人表现出色。 团队负责人对其他团队领导表现出色。

这里团队领导是一个对象,但在不同的情况下态度是不同的。

方法覆盖与方法隐藏之间的区别

方法重写允许子类提供已由基类提供的方法的特定实现。子类中的实现覆盖(替换)基类中的实现。 要记住重写的重要一点是,执行重写的方法与基类中的方法有关。 在引用上调用虚方法时,引用所引用的对象的实际类型用于确定应使用哪个方法实现。在派生类(子类)中重写基类的方法时,将使用派生类中定义的版本。即使调用应用程序不知道该对象是派​​生类的实例,也是如此。

方法隐藏在基类和派生类中的方法之间没有关系。派生类中的方法隐藏基类中的方法。

答案 3 :(得分:6)

编译时多态性

假设你说你有两种方法如下;因为该方法具有相同的名称但具有不同的参数;它被称为“重载”方法。 吃(串食); 吃(串食物,字符串SpoonOrFork);

你在晚餐课上使用这样的话

public class Man
{
 public bool Eat (string food)
 {
  //implementation
 }

 public bool Eat (string food, string SpoonOrFork)
 {
  //implementation
 }

}
public class dinner
{
  public bool Start()
  {
   string food = "course1";
   Man.Eat ( food);
  }
}

现在,当您编译此程序时,编译器确切地知道在编译期间要调用哪个版本的Eat方法(因为参数不同)。

这就是为什么它被称为编译时多态性。

运行时多态性

public class chimp
    {
        public virtual void walk()
        {
            Console.WriteLine("I am walking using 4 legs");
        }

    }

    public class neanderthals : chimp
    {
        public override void walk()
        {
            Console.WriteLine("I am walking using 2 legs");
        }

    }



    class Program
    {
        static void Main(string[] args)
        {
            chimp x = new neanderthals();
            x.walk();
            Console.ReadLine(); // this will give an output of "I am walking using 2 legs"
        }
    }

在上面的代码中, x 的类型为黑猩猩。即使编译器认为它将在黑猩猩中调用walk方法;但这不是实际发生的事情。由于它依赖于CLR(运行时),这种多态性被称为“运行时”多态。

答案 4 :(得分:3)

多态性

多态性意味着许多形式(能够采取多种形式)。在多态性中,poly表示“多个”,而变体表示“形式”,因此多态性意味着许多形式。

在多态性中,我们将在相同的类或方法中声明具有相同名称和不同参数的方法,这些方法或方法在不同的类中具有相同的名称和相同的参数。多态性能够提供以相同名称实现的方法的不同实现。

在多态性中,我们有两种不同的类型

 -  Compile Time Polymorphism (Called as Early Binding or Overloading or static binding)

 -  Run Time Polymorphism (Called as Late Binding or Overriding or dynamic binding)

编译时间多态性

编译时多态意味着我们将声明具有相同名称但签名不同的方法,因此我们将使用相同的方法名执行不同的任务。这个编译时多态也称为早期绑定或方法重载。

方法重载或编译时多态意味着具有不同签名(不同参数)的相同方法名称

有关详细信息,请在c#

中查看此链接多态性

运行时多态性

运行时多态也称为后期绑定或方法重写或动态多态。运行时多态或方法覆盖意味着具有相同签名的相同方法名称。

在这个运行时多态或方法重写中,我们可以通过在派生类中创建类似的函数来覆盖基类中的方法,这可以通过使用继承原则并使用“virtual&amp; amp;覆盖“关键字。

答案 5 :(得分:2)

它被称为运行时多态,因为行为是在运行时决定的,而不是编译时。

当您调用objectVariable.Method()之类的方法时,您的机器将调用哪个方法将取决于objectVariable中存在哪个类实例,并且在您为其分配类的实例后决定该实例。这将在运行时发生,而不是在编译时发生。因此名称为“运行时多态”。

您可以在以下网址了解详情:What is the difference between compile time and run-time polymorphism

答案 6 :(得分:1)

c#中的运行时多态性示例。

<DataMacro Event="AfterInsert">

答案 7 :(得分:0)

因为在编译时已经知道调用了哪些重载函数,但对于重写函数并不总是如此。

答案 8 :(得分:0)

静态多面体的经典示例基于template metaprogrammingDuck Typing,但不基于方法重载。

静态polimorphism意味着desicion是由compilier(静态)完成的,而动态polimorphism意味着desition只在运行时(动态)进行。

答案 9 :(得分:0)

编译时间多态性

编译时间多态性也称为方法重载。 方法重载意味着具有两个或多个具有相同名称但具有不同签名的方法。

运行时多态性

运行时多态性也称为方法覆盖。 方法覆盖意味着具有两个或多个具有相同名称和相同签名但具有不同实现的方法