早期绑定和后期绑定之间有什么区别?


81

早期绑定和晚期绑定之间有什么区别?



4
我会说早期=直接调用函数,而晚期=通过函数指针调用函数是错误的吗?永不停息​​让我惊奇的是,程序员如何拥有一种采用简单概念并使它们看起来比它们复杂得多的方式(作为智能的展示?)。从本质上来说,编程是一个非常简单的研究领域,除非您深入了解如何生成浮点类型或开发编译器。
Bob Blogge

Answers:


57

简短的答案是,早期(或静态)绑定是指编译时绑定,而后期(或动态)绑定是指运行时绑定(例如,当您使用反射时)。


8
但是维基百科有关后期绑定的文章(en.wikipedia.org/wiki/Late_binding)表示:“后期绑定通常与动态调度相混淆,但是存在显着差异”。那么它们是否相同?如果它们相同,则需要更改该维基百科页面。
亚历山大·伯德


18

在编译语言中,区别是明显的。

Java:

//early binding:
public create_a_foo(*args) {
 return new Foo(args)
}
my_foo = create_a_foo();

//late binding:
public create_something(Class klass, *args) {
  klass.new_instance(args)
}
my_foo = create_something(Foo);

在第一个示例中,编译器可以在编译时完成各种巧妙的工作。第二,您只希望希望使用该方法的人做到负责任。(当然,更新的JVM支持该Class<? extends Foo> klass结构,这可以大大降低这种风险。)

另一个好处是,IDE可以热链接到类定义,因为它是在方法中声明的。到create_something调用(美孚)可能是非常从方法的定义远远的,如果你正在寻找的方法定义,它可能会很高兴地看到实施。

后期绑定的主要优点是,它使控制反转等操作以及多态性和鸭子类型的某些其他用法(如果您的语言支持)更加容易。


6

直接来自http://word.mvps.org/fAQs/InterDev/EarlyvsLateBinding.htm

有两种方法可以使用自动化(或OLE自动化)以编程方式控制另一个应用程序。

后期绑定使用CreateObject创建应用程序对象的实例,然后可以对其进行控制。例如,使用后期绑定创建一个新的Excel实例:

 Dim oXL As Object
 Set oXL = CreateObject("Excel.Application")

另一方面,要操作Excel的现有实例(如果Excel已打开),可以使用GetObject(无论您使用的是早期绑定还是后期绑定):

 Dim oXL As Object
 Set oXL = GetObject(, "Excel.Application")

要使用早期绑定,首先需要在项目中为要处理的应用程序设置一个引用。在任何Office应用程序的VB编辑器中,或在VB本身中,都可以通过选择“工具+引用”,然后从列表中选择所需的应用程序(例如“ Microsoft Excel 8.0对象库”)来执行此操作。

要使用早期绑定创建一个新的Excel实例:

 Dim oXL As Excel.Application
 Set oXL = New Excel.Application

不管是哪种情况,您都可以首先尝试获取Excel的现有实例,如果返回错误,则可以在错误处理程序中创建一个新实例。


3
我知道此回复是旧的,并且是从其他地方获取的,但并不准确。后期绑定意味着使用CreateObject,但是CreateObject不一定意味着后期绑定。绑定不适用于实例化对象的方法,仅适用于如何声明对象。如果将对象声明为“ As Excel.Application”,则实例化它的方式无关紧要。我总是使用CreateObject实例化对外部库的对象引用,这样我就可以在早期绑定和后期绑定之间切换,而只需要切换一行(不是两行),即声明该对象的行。
JimmyPena 2011年

6

Herbert Schildt C ++书中类似但更详细的答案:

早期绑定是指在编译时发生的事件。本质上,当在编译时知道调用函数所需的所有信息时,就会发生早期绑定。(换句话说,早期绑定意味着在编译过程中绑定了对象和函数调用。)早期绑定的示例包括普通函数调用(包括标准库函数),重载函数调用和重载运算符。早期绑定的主要优点是效率。因为调用函数所需的所有信息都是在编译时确定的,所以这些类型的函数调用非常快。

早期绑定的反义词是后期绑定。后期绑定是指直到运行时才解决的函数调用。虚函数用于实现后期绑定。如您所知,当通过基本指针或引用进行访问时,实际调用的虚函数由指针指向的对象类型确定。因为在大多数情况下这不能在编译时确定,所以对象和函数在运行时才链接。后期绑定的主要优点是灵活性。与早期绑定不同,后期绑定使您可以创建可以响应程序执行时发生的事件的程序,而不必创建大量的“意外代码”。请记住,由于函数调用要等到运行时才能解决,所以后期绑定可能会使执行时间变慢。但是今天


1
“对象和函数直到运行时才链接”此语句似乎暗示一个对象在运行时之前存在。对象不是纯粹的运行时实体吗?它是编译时存在的对象的类。这可以更好地表述为“函数调用及其执行没有联系,直到运行时”
programmerravi

后期绑定的一个例子是在多态性(在OOP中),我们使用接口或抽象类,然后在运行时绑定到它。
Mohamad Mirzadeh

3

在解释型语言中,差异稍微有些微妙。

红宝石:

# early binding:
def create_a_foo(*args)
  Foo.new(*args)
end
my_foo = create_a_foo

# late binding:
def create_something(klass, *args)
  klass.new(*args)
end
my_foo = create_something(Foo)

因为Ruby通常不会被编译,所以没有编译器可以完成漂亮的前期工作。JRuby的增长意味着这些天编译了更多的Ruby,这使其行为更像上面的Java。

IDE的问题仍然存在:像Eclipse这样的平台可以在您对类定义进行硬编码时查找类定义,但是如果将其交给调用者则无法查找。

控制反转在Ruby中并不十分流行,可能是因为它具有极高的运行时灵活性,但是Rails充分利用了后期绑定来减少启动应用程序所需的配置量。


这一点也适用于已编译的语言,这些语言可能包括已编译的JIT组件,并在运行时包含以实现插件或动态框架。Java中存在一些规范的示例,当然Ruby和Python也存在。一个极端的例子是Erlang,其中运行时可以一次加载任何模块的两个版本以进行实时升级/降级。因此,尽管许多Erlang代码(大多数?)是作为静态类型的纯函数编写的,但运行时要求在后台强制进行后期绑定和动态类型。
zxq9

0
public class child()
{    public void method1()
     {     System.out.println("child1");
     }
    public void method2()
     {     System.out.println("child2");
     }

}
public class teenager extends child()
{    public void method3()
     {      System.out.println("teenager3");
     }
}
public class adult extends teenager()
{     
    public void method1()
    {    System.out.println("adult1);
         super.method1();
     }
}


//In java
public static void main(String []args)
{    ((teenager)var).method1();
}

这将打印出来

adult1
child1

在早期绑定中,编译器将可以访问child和teen中的所有方法,但在后期绑定中(在运行时),它将检查在运行时被覆盖的方法。

因此,在运行时(后期绑定),method1(来自子项-早期绑定)将被成人的method1覆盖(后期绑定),因为少年中method1中没有method1,因此它将实现子项的method1。

请注意,如果child没有method1,则main中的代码将无法编译。


0

当我们具有相同的方法名称且具有不同的行为时,编译时多态也称为重载,早期绑定或静态绑定。通过实现相同方法的多个原型,将在其中发生不同的行为。早期绑定是指程序的首次编译。但是在后期绑定对象中,运行时发生在程序中。也称为动态绑定或覆盖或运行时多态。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.