Visual Basic/面向物件程式設計
我們現在將進入 VB 的一個更高階的方面 - OOP。 但不用擔心,面向物件程式設計非常簡單,事實上,對於從未程式設計過的人來說,它可能比那些有很長時間傳統 Fortran/Basic/Pascal(選擇你最喜歡的命令式語言)程式設計經驗的人更容易。
你現在應該熟悉 VB 的事件驅動程式設計風格。 但是我會再解釋一下。 當你進行一般的 VB 程式設計時,你的思路應該遵循這種模式:“如果使用者執行此操作,應該發生什麼? 我該如何實現?” 然後你會編寫程式以適應這些問題的答案。 這就是事件驅動程式設計。 你根據使用者觸發的事件進行程式設計。 拖動圖片、單擊按鈕和輸入文字都是事件。
你,作為一名勇敢的編碼員,會問:“為什麼我必須這樣思考??”
好吧,這裡有一個供你思考的替代方法:面向物件程式設計 (OOP)。 在 OOP 世界中,你將問題分解成小部分並分別解決。 如果你要以面向物件的方式程式設計,你會將每個變數或函式視為物件的屬性,對你來說,一切看起來都像物件。 OOP 很難解釋,所以你必須在以下示例中體驗它。
想象你有一瓶果汁。 它有哪些屬性? 它有哪些事件?(它能做什麼?) 以下是我能想到的清單
Private Colour As String 'What colour?
Private Fruit As String 'What kind of fruit?
Private Volume As Single 'How much?
Public Sub MakeJuice(c As String, f As String, v As Single) 'Make some
Colour = c
Fruit = f
Volume = v
End Sub
Public Sub Evaporate() 'Well, that's the only thing I could think of
Volume = Volume - 10
End Sub
看。 這就是我們的第一個類。 現在不用擔心任何事情。 我會在後面詳細介紹這些。 無論如何,讓我們假設這個類名為“Juice”。 將其視為一瓶果汁的通用描述。 現在我們可以建立一個真正的蘋果汁瓶
Private AppleJuice As Juice 'Define
Set AppleJuice = New Juice 'Create a new instance of Juice
AppleJuice.MakeJuice "brown", "apple", 30
觀察
AppleJuice.Evaporate '20 units left
AppleJuice.Evaporate '10 left
AppleJuice.Evaporate 'Yes!!
“等等”,你又一次打斷了我的長篇大論,“但我為什麼要使用 OOP? 僅僅因為你討厭蘋果汁?”
OOP 適用於大型程式設計 - 隨著程式碼的增長,程式將擁有越來越多的過程/函式,你的程式碼將變得非常混亂,多看一眼,你就會尖叫。 這就是我教你的 OOP 的原因!(所以,與其檢視數百個分散的過程/函式,不如檢視有組織的物件。)
你可以將型別視為一種簡單的類形式。 型別只能儲存變數,不能儲存過程/函式。
在 'VB6' 中,使用者定義型別 ('UDT') 和 '類' 之間的一個重要區別是 'UDT' 是值型別,而 '類' 是引用型別。 這意味著當你將一個物件('類' 的 '例項')儲存在變數中時,實際發生的是儲存指向現有物件的指標,但當你將 'UDT' 例項儲存在變數中時,儲存的是例項的副本。 例如,假設你定義了一個類 'Class1' 和一個 UDT 'Type1'
Dim ac As Class1
Dim bc As Class1
Dim at As Type1
Dim bt As Type1
現在將 ac 賦值給 bc
Set bc = ac
並將 at 賦值給 bt
bt = at
現在對 bc 的某個屬性進行更改,並檢視 ac 中的相應屬性。 你應該會看到,當你更改 bc 時,ac 也會更改。 這是因為 ac 和 bc 實際上是指向同一記憶體塊的指標。 如果你對 bt 和 at 進行相同的操作,你應該會看到更改 bt 的屬性不會影響 at。 這是因為 at 和 bt 是值而不是引用,並且在記憶體中佔據不同的位置。
這在將物件儲存在 '集合' 中時非常重要。 如果你將物件新增到集合中,你可以在以後更改其屬性的值,集合中的物件也會發生更改。 事實上,它是一個相同的物件,因為儲存在集合中的是物件的引用('指標')。 但是,如果你將 'UDT' 儲存在集合中,儲存的是值的副本,而不是引用,因此更改原始 UDT 不會影響集合的內容。
類是子例程和型別的組合。 我的意思是,當你編寫類時,它看起來很像一個型別,但它也包含子例程和函式。
VB6 中的每個類都是一個獨立的檔案,一個檔案中只能有一個類,並且該類不能分散在多個檔案中; 這是 VB6 的一項功能,而不是面向物件程式設計的要求。
類看起來很像一個普通的模組,但副檔名為 .cls 而不是 .bas
繼承有兩種型別:實現和介面。 但是,Visual Basic Classic 僅提供介面繼承。 實現繼承可以透過介面繼承和委託的組合來模擬。
介紹繼承的一種常見方法是展示一個建立狗和貓物件或汽車和火車物件的程式。
例如,在 Visual Basic 中,我們可以像這樣宣告兩個類狗和貓
Option Explicit
Public Sub Sound()
Debug.Print "Woof"
End Sub
Option Explicit
Public Sub Sound()
Debug.Print "Meow"
End Sub
Public Sub main()
Dim oDog as cDog
Dim oCat as cCat
Set oDog = New cDog
Set oCat = New cCat
oDog.Sound
oCat.Sound
End Sub
當你執行此程式時,它將列印
Woof Meow
現在這一切都很好,直到你決定想要一個寵物陣列
Dim aPets(1 to 10) as ????
除非你將 aPets 陣列宣告為 variant,否則你必須為它指定一個型別。 一種方法是建立一個名為 cPet 的類,並使用它代替 cDog 和 cCat
Option Explicit
Public IsDog as Boolean
Public Sub Sound()
If IsDog Then
Debug.Print "Woof"
Else
Debug.Print "Meow"
End If
End Sub
現在我們的 main 例程可能看起來像這樣
Option Explicit
Dim aPet(1 to 10) as cPet
Public Sub main()
Dim lPet as Long
For lPet = 1 to 10
Set aPet(lPet) = New cPet
If lPet<=5 then
aPet(lPet).IsDog = True
Else
aPet(lPet).IsDog = False
End If
Next lPet
' Now find out what noise they make.
For lPet = 1 to 10
aPet(lPet).Sound
Next lPet
End Sub
這應該列印
Woof Woof Woof Woof Woof Meow Meow Meow Meow Meow
看起來合理嗎? 就目前所揭示的要求而言,這可以正常工作。 但是,當你發現貓會做一些狗不會做的事情時會發生什麼? 其他型別的寵物怎麼樣? 例如,你希望你的貓發出呼嚕聲。 你可以有一個名為 purr 的方法,但你該把它放在哪裡? 它肯定不屬於 cPet,因為狗不會發出呼嚕聲,豚鼠和魚也不會。
要做的事情是將所有寵物共有的那些特性分離出來,並建立一個只處理這些特性的類,我們可以為此目的重寫cPet。 現在,我們可以回到我們最初的 cDog 和 cCat 類,並修改它們以從 cPet 繼承介面。
Option Explicit
Public Sub Sound()
End Sub
請注意,Sound方法是空的。這是因為它的存在只是為了定義介面。介面就像插頭或插座上的引腳佈局;任何具有相同佈局、大小和形狀的插頭都可以插入實現相同介面的插座。您插入的東西內部發生了什麼是一個單獨的問題;吸塵器和電視機都使用相同的電源插頭。
為了使這工作,我們現在必須修改 cDog 和 cCat。
Option Explicit
Implements cPet
Private Sub cPet_Sound()
Debug.Print "Woof"
End Sub
Option Explicit
Implements cPet
Private Sub cPet_Sound()
Debug.Print "Meow"
End Sub
Public Sub Purr()
Debug.Print "Purr"
End Sub
在上面的寵物示例中,cPet 物件的陣列用於儲存寵物。如果您確切知道有多少寵物,這很有效。但是,如果您收養了另一隻流浪的小狗,或者您的貓生下了小貓,會發生什麼情況呢?
一種解決方案是使用 Collection 物件而不是陣列。Collection 物件看起來有點像陣列,但它允許您新增和刪除專案,而不必擔心已宣告的大小,它會自動擴充套件和收縮。
| 本節是一個存根。 您可以透過擴充套件它來幫助華夏公益教科書。 |
| 上一頁:External_Processes | 目錄 | 下一頁:Effective Programming |