【问题标题】:What is the difference between static and dynamic binding?静态绑定和动态绑定有什么区别?
【发布时间】:2020-01-09 06:09:49
【问题描述】:

绑定时间可以分为两种类型:静态和动态。静态绑定和动态绑定有什么区别?

你能举一个简单的例子来进一步说明吗?

【问题讨论】:

  • 如果是家庭作业,你最好要求对你计划的反应提出批评;不是为了直接回答。
  • @Daniel L,我将其标记为作业。这不是我作业中的直接问题。我必须将一堆事情分类为静态或动态,我试图通过这个问题在我的脑海中弄清楚这是哪个。如果人们想回答他们会的。
  • @KingNestor:是的,我看到这是家庭作业;] 我明白你现在的意思了。

标签: programming-languages language-design


【解决方案1】:

在最一般的术语中,静态绑定意味着在编译时解析引用

Animal a = new Animal();
a.Roar(); // The compiler can resolve this method call statically.

动态绑定意味着引用在运行时解析

public void MakeSomeNoise(object a) {
   // Things happen...
   ((Animal) a).Roar(); // You won't know if this works until runtime!
}

【讨论】:

  • 不正确,如果对象 a = new Animal();
  • 是的,虽然我认为很明显我试图笼统地说。我稍微调整了一下。
  • 你后面的例子仍然是静态绑定。 typecast 可能成功也可能不成功,但是如果 typecast 成功,即使Roar 是一个虚方法,代码也会绑定到与Animal.Roar() 静态关联的vtable slot。只有在使用新的 dynamic 类型或使用反射(例如 a.GetType().GetMethod("Roar").Invoke(a, null))时,动态绑定才会在 C# 中发生。后者适用于任何实现称为Roar 的无参数方法的类型,并返回最派生的实现(即使基本实现是非虚拟的)。
  • @supercat java 也有反射,早在 1999 年 .net 甚至还没有一个想法!见stackoverflow.com/questions/940844/getmethods-java
  • @supercat 你错了。 C++、Java 和 C# 等语言在调用虚函数/方法时肯定会使用动态绑定。 Vtables 提供了安全性并缩短了查找时间,但在运行时仍然有效地选择了正确的方法。与 C#dynamic、反射和动态语言一起使用的查找类型有时称为 late binding,尽管 latedynamic 通常称为可以互换使用,区别不明显。不管怎样,John Feminella 的第二个例子绝对是dynamic,而不是static,绑定。
【解决方案2】:

这取决于绑定发生的时间:编译时(静态)或运行时(动态)。调用简单类方法时使用静态绑定。当您开始处理类层次结构和虚方法时,编译器将开始使用所谓的VTABLEs。那时编译器并不确切知道要调用什么方法,它必须等到运行时才能确定要调用的正确方法(这是通过VTABLE 完成的)。这称为动态绑定。

有关更多详细信息和参考,请参阅 Virtual tables 上的 Wikipedia 文章。

【讨论】:

    【解决方案3】:

    我遇到了一个 quora 用户“Monis Yousuf”的完美答案。他完美地解释了这一点。我把它放在这里供其他人使用。

    绑定主要是面向对象编程中与多态性相关的一个概念。

    首先,了解什么是多态。书上说它的意思是“一个名字和多种形式”。没错,但太抽象了。让我们举一个现实生活中的例子。你去看“医生”,医生可能是眼科专家、耳鼻喉科专家、神经外科医生、顺势疗法医生等。

    这里的“医生”是一个名字,可以有多种类型;每个人都执行自己的功能。这是现实生活中的多态性。

    函数重载:这个概念描述了静态绑定。函数重载大致可以定义为,两个或多个同名但签名不同(包括参数个数、参数类型、返回类型不同)的方法(函数)称为重载方法(或函数)。

    假设您必须计算矩形和圆形的面积。见以下代码:-

    class CalculateArea {
    
        private static final double PI = 3.14;
    
        /* 
           Method to return area of a rectangle 
           Area of rectangle = length X width
        */
        double Area(double length, double width) {
            return (length * width);
        }
    
        /*
          Method to return area of circle
          Area of circle = π * r * r
        */
        double Area(double radius) {
            return PI * radius * radius;
        }
    }
    

    在上面的代码中,有两个参数不同的方法“Area”。这种情况属于函数重载。

    现在,进入真正的问题:这个静态绑定如何?

    当您在代码中调用上述任何函数时,您必须指定要传递的参数。在这种情况下,您将通过:

    • 双精度类型的两个参数[将调用第一个方法,以 计算矩形]
    • double类型的单参数[调用第二种方法,计算圆的面积]

    因为在编译时 java 编译器可以确定调用哪个函数,它是编译时(或静态)绑定。

    函数覆盖:函数覆盖是一个在继承中显示的概念。大致可以定义为:当父类中存在一个方法,而其子类也有相同的签名方法相同时,称为函数覆盖。 [还有更多,但为了简单起见,我写了这个定义]下面的代码会更容易理解。

    class ParentClass {
        int show() {
            System.out.println("I am from parent class");
        }
    }
    
    class ChildClass extends ParentClass{
        int show() {
            System.out.println("I am from child class");
        }
    }
    
    class SomeOtherClass {
        public static void main (String[] s) {
            ParentClass obj = new ChildClass();
            obj.show();
        }
    }
    

    在上面的代码中,show() 方法被覆盖,因为父类和子类中都存在相同的签名(和名称)。

    在第三个类SomeOtherClass中,ParentClass类型的引用变量(obj)保存了ChildClass的对象。接下来,从同一个引用变量(obj)调用方法show()。

    同样的问题:这个动态绑定如何?

    在编译时,编译器检查 Reference 变量的类型是否为 ParentClass,并检查该类中是否存在方法 show()。一旦它检查到这一点,编译就成功了。

    现在,当程序运行时,它看到对象属于ChildClass,因此它运行ChildClassshow() 方法。由于此决定是在 RUNTIME 进行的,因此称为 Dynamic Binding(或 Run-time Polymorphism)。

    Link原始答案

    【讨论】:

      【解决方案4】:

      静态绑定:在编译时解析类型、成员和操作的过程。 例如:

      Car car = new Car();
      car.Drive();
      

      在此示例中,编译器通过在 car 对象上查找无参数的 Drive 方法来执行绑定。如果没有找到那个方法!搜索采用optional parameters 的方法,如果没有找到该方法,则再次搜索Carbase class 以查找该方法,如果未找到该方法,则再次搜索extension methods 以查找Car 类型。如果找不到匹配项,您将收到编译错误!

      在这种情况下,绑定是由编译器完成的,并且绑定依赖于静态地知道对象的类型。这使它成为静态绑定。

      动态绑定:动态绑定将绑定(解析类型、成员和操作的过程)从编译时推迟到运行时。 例如:

      dynamic d = new Car();
      d.Drive();
      

      一个动态类型告诉编译器我们期望d运行时类型Drive方法,但是我们不能静态地证明它 。由于d 是动态的,编译器将Drive 的绑定推迟到d 直到运行时

      动态绑定对于在编译时我们知道某个函数、操作成员存在但编译器不知道的情况很有用!这通常发生在我们与动态编程语言COM反射交互操作时。

      【讨论】:

        【解决方案5】:

        在编译时完成的绑定是静态绑定,在运行时完成的绑定是动态绑定。在静态绑定中,指针的数据类型决定调用哪个方法。但在动态绑定中,对象的数据类型决定调用哪个方法。

        【讨论】:

          【解决方案6】:

          * 执行时间:-* 变量与其值的绑定,以及变量在执行时与特定存储位置的绑定称为执行时间绑定。

          它可能有两种类型

          1. 进入子程序。
          2. 在执行期间的任意时间点。

          编译时间绑定:-(翻译时间) 它由以下内容组成。

          1. 程序员选择的绑定。
          2. 翻译者选择的绑定。
          3. 加载程序选择的绑定。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2010-12-10
            • 1970-01-01
            • 1970-01-01
            • 2014-03-30
            • 2012-10-29
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多