1. 什么是后期綁定和前期綁定后期綁定
MSDN 6的定義如下:
后期綁定:若將一個(gè)變量聲明為 As Object 或 As Variant(包括 As Form 或 As Control 的變量),Visual Basic 在編譯時(shí)就無法確定該變量將引用哪種類型的對象。因此,Visual Basic 必須使用后期綁定,在運(yùn)行時(shí)確定對象的屬性和方法能否使用該變量。
若使用后期綁定,則每次調(diào)用屬性或方法時(shí),Visual Basic 都要將成員名傳給該對象 IDispatch 接口的 GetIDsOfNames 方法。GetIDsOfNames 返回該成員的派遣 ID,或 DispID。Visual Basic 再將該 DispID 傳給 IDispatch 接口的 Invoke 方法來調(diào)用該成員。
對進(jìn)程外部件而言,這意味著一次額外的跨進(jìn)程方法調(diào)用,結(jié)果是調(diào)用開銷翻番。
前期綁定:如果在編譯時(shí) Visual Basic 能夠知道屬性或方法所屬的對象,就可以預(yù)先查找該成員在類型庫中的 DispID 或 vtable 地址。這樣就無須在運(yùn)行時(shí)調(diào)用 GetIDsOfNames。
當(dāng)顯式聲明了變量的類時(shí),例如 As Widget,該變量就只能存放該類的對象的引用。Visual Basic 就可以為該變量調(diào)用的所有屬性和方法使用前期綁定。
建議在 Visual Basic 和應(yīng)用程序中使用這種方法來聲明對象變量。
使用前期綁定還是后期綁定完全取決于聲明變量的方式。對象的創(chuàng)建方式對此沒有任何影響。
2. 后期綁定的幾個(gè)優(yōu)勢和好處
第一,個(gè)人認(rèn)為,由于VB6不支持實(shí)現(xiàn)繼承,對于某些設(shè)計(jì),可以使用將對象定義為Variant變量,而獲取某些設(shè)計(jì)和編碼上的便利,而得到接口或抽象類的好處。例如:
如定義2個(gè)類:
Class1:
1Option Explicit
2
3Public Sub Update()
4 MsgBox "Class1 Updated"
5End Sub
Class2:
1Option Explicit
2
3Public Sub Update()
4 MsgBox "Class2 Updated"
5End Sub
在使用的時(shí)候,可以使用以下方法,而實(shí)現(xiàn)一些設(shè)計(jì)模式:
1Dim objTest As Variant
2
3Dim objC1 As New Class1
4Set objTest = objC1
5objTest.Update
6
7Dim objC2 As New Class2
8Set objTest = objC2
9objC2.Test
10
這樣,無須繼承機(jī)制,也可以得到抽象接口的優(yōu)勢,而使接口、實(shí)現(xiàn)分離。
第二,在調(diào)用外部的COM自動(dòng)化組件時(shí),如Office,如果通過這種方式調(diào)用,對于不同版本的Office,如果你調(diào)用的方法、屬性都是存在的,那么可以適應(yīng)不同版本的Office,但如果通過前期綁定,在項(xiàng)目引用中確定對象類型,是有版本兼容問題的。
3. 效率和劣勢
其實(shí)最主要的劣勢是效率問題,《Advanced Visual Basic 6》一書說,使用Variant變量和Long變量進(jìn)行循環(huán),效率差別是1.5倍,而沒有別人認(rèn)為的那么大,而且對于大對象,差別也不是很大。對于本文前邊的例子,如果創(chuàng)建的是進(jìn)程內(nèi)對象,前期綁定和后期綁定調(diào)用效率差別大概2:3左右,也就是說也是1.5倍。對于調(diào)用Office這樣的外部COM自動(dòng)化對象,也許差別大一些,沒有專門測試,不過對于Office自動(dòng)化,速度主要是決定于Office本身的啟動(dòng)、初始化。
另外一個(gè)劣勢是沒有了IDE下的屬性、方法成員自動(dòng)列出。
所以,個(gè)人認(rèn)為,在使用VB6的時(shí)候,為了得到好的設(shè)計(jì),有時(shí)不妨使用一些VB6的后期綁定的特性,來提高設(shè)計(jì)質(zhì)量。
MSDN 6的定義如下:
后期綁定:若將一個(gè)變量聲明為 As Object 或 As Variant(包括 As Form 或 As Control 的變量),Visual Basic 在編譯時(shí)就無法確定該變量將引用哪種類型的對象。因此,Visual Basic 必須使用后期綁定,在運(yùn)行時(shí)確定對象的屬性和方法能否使用該變量。
若使用后期綁定,則每次調(diào)用屬性或方法時(shí),Visual Basic 都要將成員名傳給該對象 IDispatch 接口的 GetIDsOfNames 方法。GetIDsOfNames 返回該成員的派遣 ID,或 DispID。Visual Basic 再將該 DispID 傳給 IDispatch 接口的 Invoke 方法來調(diào)用該成員。
對進(jìn)程外部件而言,這意味著一次額外的跨進(jìn)程方法調(diào)用,結(jié)果是調(diào)用開銷翻番。
前期綁定:如果在編譯時(shí) Visual Basic 能夠知道屬性或方法所屬的對象,就可以預(yù)先查找該成員在類型庫中的 DispID 或 vtable 地址。這樣就無須在運(yùn)行時(shí)調(diào)用 GetIDsOfNames。
當(dāng)顯式聲明了變量的類時(shí),例如 As Widget,該變量就只能存放該類的對象的引用。Visual Basic 就可以為該變量調(diào)用的所有屬性和方法使用前期綁定。
建議在 Visual Basic 和應(yīng)用程序中使用這種方法來聲明對象變量。
使用前期綁定還是后期綁定完全取決于聲明變量的方式。對象的創(chuàng)建方式對此沒有任何影響。
2. 后期綁定的幾個(gè)優(yōu)勢和好處
第一,個(gè)人認(rèn)為,由于VB6不支持實(shí)現(xiàn)繼承,對于某些設(shè)計(jì),可以使用將對象定義為Variant變量,而獲取某些設(shè)計(jì)和編碼上的便利,而得到接口或抽象類的好處。例如:
如定義2個(gè)類:
Class1:
1Option Explicit
2
3Public Sub Update()
4 MsgBox "Class1 Updated"
5End Sub
Class2:
1Option Explicit
2
3Public Sub Update()
4 MsgBox "Class2 Updated"
5End Sub
在使用的時(shí)候,可以使用以下方法,而實(shí)現(xiàn)一些設(shè)計(jì)模式:
1Dim objTest As Variant
2
3Dim objC1 As New Class1
4Set objTest = objC1
5objTest.Update
6
7Dim objC2 As New Class2
8Set objTest = objC2
9objC2.Test
10
這樣,無須繼承機(jī)制,也可以得到抽象接口的優(yōu)勢,而使接口、實(shí)現(xiàn)分離。
第二,在調(diào)用外部的COM自動(dòng)化組件時(shí),如Office,如果通過這種方式調(diào)用,對于不同版本的Office,如果你調(diào)用的方法、屬性都是存在的,那么可以適應(yīng)不同版本的Office,但如果通過前期綁定,在項(xiàng)目引用中確定對象類型,是有版本兼容問題的。
3. 效率和劣勢
其實(shí)最主要的劣勢是效率問題,《Advanced Visual Basic 6》一書說,使用Variant變量和Long變量進(jìn)行循環(huán),效率差別是1.5倍,而沒有別人認(rèn)為的那么大,而且對于大對象,差別也不是很大。對于本文前邊的例子,如果創(chuàng)建的是進(jìn)程內(nèi)對象,前期綁定和后期綁定調(diào)用效率差別大概2:3左右,也就是說也是1.5倍。對于調(diào)用Office這樣的外部COM自動(dòng)化對象,也許差別大一些,沒有專門測試,不過對于Office自動(dòng)化,速度主要是決定于Office本身的啟動(dòng)、初始化。
另外一個(gè)劣勢是沒有了IDE下的屬性、方法成員自動(dòng)列出。
所以,個(gè)人認(rèn)為,在使用VB6的時(shí)候,為了得到好的設(shè)計(jì),有時(shí)不妨使用一些VB6的后期綁定的特性,來提高設(shè)計(jì)質(zhì)量。

