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

时间:2008-08-14 02:10:54

标签: binding dynamic-binding static-binding

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

8 个答案:

答案 0 :(得分:58)

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

答案 1 :(得分:15)

在编译语言中,差异很明显。

爪哇:

//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(Foo)的调用可能非常远离方法定义,如果您正在查看方法定义,那么查看实现可能会很好。

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

答案 2 :(得分: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")
     

要使用早期绑定,首先需要在您的设置中设置引用   项目到您想要操作的应用程序。在VB编辑器中   任何Office应用程序,或在VB本身,您通过选择   工具+参考,并从中选择所需的应用程序   列表(例如“Microsoft Excel 8.0对象库”)。

     

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

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

在任何一种情况下,顺便说一下,你可以先尝试获得一个现有的   Excel的实例,如果返回错误,则可以创建新的   错误处理程序中的实例。

答案 3 :(得分:4)

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

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

早期结合的反义词是晚期结合。后期绑定是指 处理在运行时才解决的调用。虚函数用于实现后期绑定。如您所知,当通过基指针或引用进行访问时,实际调用的虚函数由指针指向的对象类型决定。因为在大多数情况下无法在编译时确定,所以在运行时之前不会链接对象和函数。后期绑定的主要优点是灵活性。与早期绑定不同,后期绑定允许您创建程序,这些程序可以响应程序执行时发生的事件而无需创建 大量的“应急代码”。请记住,因为函数调用直到运行时才解决,所以后期绑定可能会导致执行时间稍慢。 然而,今天,快速计算机显着缩短了与后期绑定相关的执行时间。

答案 4 :(得分: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很好地利用了后期绑定来减少使应用程序运行所需的配置量。

答案 5 :(得分: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

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

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

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

答案 6 :(得分:0)

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

答案 7 :(得分:0)

Java 中最简单的例子:

早期(静态或重载)绑定:

public class Duck {
    public static void quack(){
        System.out.println("Quack");
    }
}

public class RubberDuck extends Duck {
    public static void quack(){
        System.out.println("Piiiiiiiiii");
    }
}

public class EarlyTest {
    public static void main(String[] args) {
        Duck duck = new Duck();
        Duck rubberduck = new RubberDuck();

        duck.quack();
        rubberduck.quack(); //early binding - compile time
    }
}

结果是:

Quack
Quack

while 用于后期(动态或覆盖)绑定:

public class Duck {
    public void quack(){
        System.out.println("Quack");
    }
}

public class RubberDuck extends Duck {
    public void quack(){
        System.out.println("Piiiiiiiiii");
    }
}

public class LateTest {
    public static void main(String[] args){
        Duck duck = new Duck();
        Duck rubberduck = new RubberDuck();

        duck.quack();
        rubberduck.quack(); //late binding - runtime
    }
}

结果是:

Quack
Piiiiiiiiii

早期绑定发生在编译时,而后期绑定发生在运行时。