名字绑定
在程式设计语言中,名字绑定是把实体(数据或/且代码)关联到标识符。[1]标识符绑定到实体被称为引用该对象。机器语言没有内建的标识符表示方法,但程序设计语言实现了名字与对象的绑定。绑定最初是与作用域相关,因为作用域确定了哪个名字绑定到哪个对象——在程序代码中的哪个位置与哪条执行路径。
绑定时机
- 静态绑定(Static binding)或称早绑定(early binding):名字绑定发生在程序开始运行之前。[2]
- 动态绑定(Dynamic binding)或称迟绑定(late binding)、虚绑定(virtual binding):名字绑定发生在程序运行时。[2]
静态绑定的例子,如C语言的函数调用:用标识符引用的函数在运行时不能改变。
动态绑定的例子如C++虚函数调用时的动态分派。由于多态对象的具体类型在运行前是未知的,因此被执行函数需要动态绑定。
public void foo(java.util.List<String> list) {
list.add("bar");
}
List
是一个接口,因此list
必须引用到它的子类型。它是引用到LinkedList
,ArrayList
或List
的其它子类型?add
实际引用到的方法在运行时之前也是未知的。C语言中,这种动态绑定可以通过调用一个函数指针类型的变量或表达式,其值直到运行时求值之前都是未知的。
重绑定与变异
重绑定不能与变异混淆:
- 重绑定(Rebinding)是改变引用的标识符;
- 变异(Mutation)是改变被引用的实体。
考虑下面Java代码:
LinkedList<String> list;
list = new LinkedList<String>();
list.add("foo");
list = null;
标识符list
最初引用到空(未初始化);然后重绑定到一个对象(一个字符串链表);这个被list
引用的字符串链表被变异,即增加一个字符串到该链表;最后,list
被重绑定到null
。
静态迟绑定
静态迟绑定(late static binding)是静态绑定与动态绑定之间的一个变种。考虑下述PHP例子:
class A
{
static $word = "hello";
static function hello() { print self::$word; }
}
class B extends A
{
static $word = "bye";
}
B::hello();
在上例中,PHP解释器把A::hello()
关键字self
绑定到类A
,因此B::hello()
打印出字符串"hello"。如果self::$word
的语义是基于静态迟绑定,结果就是"bye"。
从PHP版本5.3开始支持静态迟绑定。[3]具体说,上例中的self::$word
如果改为下例中的static::$word
,关键字static
指示运行时才绑定,B::hello()
的调用结果将是"bye":
class A
{
static $word = "hello";
static function hello() { print static::$word; }
}
class B extends A
{
static $word = "bye";
}
B::hello();
参见
参考文献
- ^ Microsoft, Using early binding and late binding in Automation, Microsoft, May 11, 2007 [May 11, 2009], (原始内容存档于2015-02-22)
- ^ 2.0 2.1 Systems and software engineering — Vocabulary ISO/IEC/IEEE 24765:2010(E), IEEE, Dec 15, 2010
- ^ Late Static Bindings. [July 3, 2013]. (原始内容存档于2019-02-21).