2024年6月10日 星期一

13.VB.NET 筆記 進階篇 - 建構式 (Constructor)

VB.NET 建構式 (Constructor) 筆記 (進階篇)

VB.NET 建構式 (Constructor) 筆記 (進階篇)

建構式就像是建築物的地基,是物件創建的起點。它負責初始化物件的成員變數,並執行一些必要的設置工作,使物件能夠正常工作。透過理解建構式的語法和使用方式,就能夠靈活地定義物件的初始狀態,提高程式的可讀性和可維護性。

認識建構式

建構式 (Constructor): 建構式是一種特殊的方法,用於在創建類別的實例時初始化物件的狀態。它與類別同名,沒有返回類型,可以接受參數。

VB.NET 中的建構式有以下幾個重要特性:

  1. 自動調用當使用 New 關鍵字創建類別的實例時,會自動調用建構式。:建構式在創建物件時自動被調用,不需要顯式調用。
  2. 初始化成員建構式的主要任務是初始化物件的成員變數,可以在建構式中為成員變數賦予初始值。:建構式負責初始化物件的成員變數,確保物件在創建時處於一個有效的狀態。
  3. 多個建構式一個類別可以有多個建構式,通過參數的數量和類型來區分。這稱為建構式重載。:一個類別可以有多個建構式,稱為建構式重載。不同的建構式可以接受不同的參數,以實現不同的初始化邏輯。
  4. 繼承與建構式子類別的建構式在執行時,會先調用父類別的建構式,然後再執行自己的初始化邏輯。:在繼承關係中,子類別的建構式需要調用父類別的建構式,以確保父類別的初始化邏輯得到執行。

以下是建構式的基本語法:

Public Sub New(Optional 參數列表)
    ' 初始化邏輯
End Sub

其中,Public 表示建構式的訪問修飾符,Sub 表示這是一個子程序,New 是建構式的關鍵字,參數列表 是可選的參數列表,用於接受創建物件時傳遞的參數。

建構式的命名必須與類別名稱相同,並且沒有返回類型。每個類別至少有一個建構式,如果沒有顯式定義建構式,編譯器會自動生成一個預設建構式。

建構式的作用是在創建物件時執行必要的初始化工作,如為成員變數賦予初始值、分配資源等。通過參數化的建構式,可以在創建物件時動態地設置物件的初始狀態。

以下是一個簡單的建構式範例:

Public Class Person
    Private name As String
    Private age As Integer
    
    Public Sub New(ByVal name As String, ByVal age As Integer)
        Me.name = name
        Me.age = age
    End Sub
End Class

在這個範例中,Person 類別有兩個私有成員變數 nameage,以及一個帶有兩個參數的建構式。建構式接受 nameage 作為參數,並將它們賦值給對應的成員變數。

使用建構式創建 Person 物件的方式如下:

Dim person As New Person("John", 25)

這樣就創建了一個名為 personPerson 物件,並將其 name 設置為 "John",age 設置為 25。

建構式重載

一個類別可以有多個建構式,稱為建構式重載。建構式重載允許提供多種方式來創建和初始化物件,以適應不同的需求。

建構式重載的規則如下:

  • 建構式的名稱必須與類別名稱相同。
  • 建構式之間必須有不同的參數簽名,即參數的數量或類型必須不同。
  • 建構式可以有不同的訪問修飾符,如 PublicPrivateProtected 等。

以下是一個建構式重載的範例:

Public Class Rectangle
    Private width As Double
    Private height As Double
    
    Public Sub New()
        Me.width = 0
        Me.height = 0
    End Sub
    
    Public Sub New(ByVal width As Double, ByVal height As Double)
        Me.width = width
        Me.height = height
    End Sub
    
    Public Sub New(ByVal size As Double)
        Me.width = size
        Me.height = size
    End Sub
End Class

在這個範例中,Rectangle 類別有三個建構式:

  1. 無參數建構式:初始化 widthheight 為 0。
  2. 帶有兩個 Double 類型參數的建構式:分別初始化 widthheight
  3. 帶有一個 Double 類型參數的建構式:將 widthheight 都初始化為該參數的值,表示正方形。

使用不同的建構式創建 Rectangle 物件的方式如下:

Dim rect1 As New Rectangle()
Dim rect2 As New Rectangle(5, 3)
Dim rect3 As New Rectangle(4)

rect1 使用無參數建構式創建,表示一個寬度和高度都為 0 的矩形;rect2 使用帶有兩個參數的建構式創建,表示一個寬度為 5、高度為 3 的矩形;rect3 使用帶有一個參數的建構式創建,表示一個寬度和高度都為 4 的正方形。

建構式重載提供了靈活的方式來創建和初始化物件,使得可以根據不同的需求選擇合適的建構式。這樣可以提高程式的可讀性和可維護性,並減少了創建物件時的錯誤。

簡單理解建構式

建構式就像是一個特殊的方法,它的作用是在創建一個新的物件時,幫助初始化該物件的屬性和狀態。可以把建構式想像成一個"製造機器人的說明書"。

假設要製造一個機器人,需要給機器人取一個名字,設置它的初始電量,並啟動它的基本功能。這就是建構式要做的事情。

Public Class Robot
    Public Name As String
    Public BatteryLevel As Integer
    
    Public Sub New(ByVal robotName As String, ByVal initialBattery As Integer)
        Name = robotName
        BatteryLevel = initialBattery
        ActivateBasicFunctions()
    End Sub
    
    Private Sub ActivateBasicFunctions()
        ' 啟動機器人的基本功能
    End Sub
End Class

在這個例子中,當創建一個新的機器人物件時,需要給它一個名字和初始電量,建構式就會幫完成這些初始化的工作。它會將傳入的名字和電量設置給機器人的屬性,然後呼叫一個方法來啟動機器人的基本功能。

建構式還可以有多個,每個建構式接受不同的參數,這樣就可以根據需要,用不同的方式來創建和初始化機器人了。

' 創建一個名字為 "Marvin",初始電量為 100 的機器人
Dim robot1 As New Robot("Marvin", 100)

' 創建一個名字為 "Rosie",初始電量為 50 的機器人  
Dim robot2 As New Robot("Rosie", 50)

建構式的作用就是在創建新物件時,自動完成必要的初始化工作,讓物件可以正常工作。它讓在創建物件的同時,就能方便地設置物件的屬性和初始狀態,而不需要額外的程式碼。

建構式的成員

在 VB.NET 中,建構式作為一種特殊的方法,具有以下成員:

成員 說明
訪問修飾符 用於指定建構式的可訪問性,可以是 PublicPrivateProtectedFriendProtected Friend。預設為 Public
參數列表 指定建構式接受的參數列表,包括參數的名稱、類型和可選的預設值。建構式可以沒有參數,也可以有多個參數。
程式碼區塊 包含建構式的程式碼實現,用於執行初始化邏輯,如為成員變數賦值、呼叫其他方法等。

以下是一個包含完整成員的建構式範例:

Public Class MyClass
    Private name As String
    
    Public Sub New(ByVal name As String)
        Me.name = name
        ' 其他初始化邏輯
    End Sub
End Class

在這個範例中,建構式的訪問修飾符為 Public,參數列表包含一個名為 nameString 類型參數,程式碼區塊中將參數 name 的值賦給了類別的私有成員變數 name

建構式的屬性

雖然建構式本身沒有顯式的屬性,但它與以下兩個重要的屬性密切相關:

屬性 說明
參數的屬性 建構式的參數可以使用 ByValByRef 關鍵字來指定參數的傳遞方式,以及使用 Optional 關鍵字來指定參數是否可選。
類別的屬性 建構式常常用於初始化類別的屬性(即成員變數)。在建構式中,可以為類別的屬性賦予初始值或根據參數的值進行設置。

以下是一個展示參數屬性和初始化類別屬性的建構式範例:

Public Class Person
    Private name As String
    Private age As Integer
    
    Public Sub New(ByVal name As String, Optional ByVal age As Integer = 0)
        Me.name = name
        Me.age = age
    End Sub
End Class

在這個範例中,建構式有兩個參數:nameagename 參數使用 ByVal 關鍵字來指定按值傳遞,而 age 參數使用 Optional 關鍵字來指定它是可選的,並提供了預設值 0。在建構式的程式碼區塊中,這兩個參數的值被用於初始化 Person 類別的 nameage 屬性。

建構式的方法

建構式作為一種特殊的方法,它不能被顯式呼叫,而是在創建類別實例時自動呼叫。除了建構式本身,還有幾個與建構式相關的方法:

方法 說明
Finalize 這是一個受保護的方法,用於在物件被垃圾回收垃圾回收是 .NET 框架自動進行的記憶體管理機制,用於釋放不再使用的物件所佔用的記憶體。之前執行清理邏輯。它不應該被顯式呼叫,而是由 .NET Framework 自動呼叫。
Dispose 這是一個公共方法,用於釋放物件所持有的非託管資源非託管資源是指不受 .NET 框架管理的資源,如檔案句柄、資料庫連接等。這些資源需要顯式釋放。。它通常在實現 IDisposable 介面時使用,可以被顯式呼叫。
Object Initializer 這是一種特殊的語法,允許在創建物件時同時設置其屬性的值,而無需顯式呼叫建構式。它使用大括號 {} 和成員初始化語法。

以下是一個展示 Dispose 方法和物件初始化器物件初始化器是一種簡潔的語法,用於在創建物件的同時設置其屬性的值,而無需顯式呼叫建構式。的範例:

Public Class MyResource
    Implements IDisposable
    
    Private resource As IntPtr
    
    Public Sub New()
        ' 分配非託管資源
        resource = AllocateResource()
    End Sub
    
    Public Sub Dispose() Implements IDisposable.Dispose
        ' 釋放非託管資源
        ReleaseResource(resource)
    End Sub
End Class

' 使用物件初始化器創建物件並設置屬性
Dim obj As New MyClass With {.Property1 = value1, .Property2 = value2}

在這個範例中,MyResource 類別實現了 IDisposable 介面,並在 Dispose 方法中釋放了非託管資源。物件初始化器的使用展示了如何在創建物件的同時設置其屬性的值,而無需顯式呼叫建構式。

通過對建構式的成員、屬性和方法的深入理解,可以更好地掌握建構式的工作原理,並在實踐中靈活運用它們來初始化物件和管理資源。

建構式與繼承

在繼承關係中,子類別的建構式需要調用父類別的建構式,以確保父類別的初始化邏輯得到執行。這是因為子類別繼承了父類別的成員變數,而這些成員變數需要在父類別的建構式中進行初始化。

在 VB.NET 中,子類別的建構式可以使用 MyBase 關鍵字來調用父類別的建構式。MyBase 關鍵字後面跟著父類別建構式的參數列表。

以下是一個建構式與繼承的範例:

Public Class Animal
    Protected name As String
    
    Public Sub New(ByVal name As String)
        Me.name = name
    End Sub
End Class

Public Class Dog
    Inherits Animal
    
    Private breed As String
    
    Public Sub New(ByVal name As String, ByVal breed As String)
        MyBase.New(name)
        Me.breed = breed
    End Sub
End Class

在這個範例中,Animal 是父類別,它有一個受保護的成員變數 name 和一個帶有一個參數的建構式。Dog 是子類別,它繼承了 Animal 類別,並添加了一個私有成員變數 breed

Dog 類別的建構式接受兩個參數:namebreed。在建構式中,它使用 MyBase.New(name) 調用父類別的建構式,將 name 參數傳遞給父類別的建構式。然後,它將 breed 參數賦值給 Dog 類別自己的成員變數 breed

使用 Dog 類別創建物件的方式如下:

Dim dog As New Dog("Buddy", "Labrador")

這樣就創建了一個名為 dogDog 物件,它的 name 是 "Buddy",breed 是 "Labrador"。在創建 Dog 物件時,會先調用 Animal 類別的建構式初始化 name,然後再執行 Dog 類別自己的初始化邏輯。

在繼承關係中使用建構式時需要注意以下幾點:

  • 子類別的建構式必須調用父類別的建構式,除非父類別有一個無參數的建構式。
  • 子類別的建構式中,MyBase.New 語句必須出現在任何其他程式碼之前。
  • 如果父類別沒有無參數的建構式,子類別就必須顯式調用父類別的某個建構式。

透過在子類別的建構式中調用父類別的建構式,可以確保父類別的初始化邏輯得到執行,並正確地初始化繼承的成員變數。這有助於維護物件的一致性和正確性。

建構式應用範例

以下是一個完整的 VB.NET 範例,展示了如何使用建構式來創建和初始化寵物物件,並透過視窗元件與使用者進行互動。

範例:寵物養成遊戲

這個範例允許使用者選擇寵物的類型(狗或貓),輸入寵物的名字和初始體力值,並使用這些資訊創建寵物物件。使用者可以執行餵食和玩耍操作,並查看寵物的當前體力值。

使用的控制項:
  • ComboBox1:用於選擇寵物的類型(狗或貓)。
  • TextBox1:用於輸入寵物的名字。
  • TextBox2:用於輸入寵物的初始體力值。
  • Button1:用於創建寵物物件。
  • Button2:用於執行餵食操作。
  • Button3:用於執行玩耍操作。
  • Label1:用於顯示寵物的當前體力值。
Imports System ' 導入 System 命名空間

Public Class Form1
    Private pet As Pet ' 宣告一個 Pet 類型的變數
    
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        ' 在下拉式選單中添加寵物類型選項
        ComboBox1.Items.Add("狗")
        ComboBox1.Items.Add("貓")
        ComboBox1.SelectedIndex = 0 ' 預設選擇第一個選項(狗)
    End Sub
    
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        ' 獲取使用者選擇的寵物類型、名字和初始體力值
        Dim petType As String = ComboBox1.SelectedItem.ToString()
        Dim name As String = TextBox1.Text
        Dim energy As Integer = Integer.Parse(TextBox2.Text)
        
        ' 根據寵物類型創建對應的寵物物件
        If petType = "狗" Then
            pet = New Dog(name, energy)
        ElseIf petType = "貓" Then
            pet = New Cat(name, energy)
        End If
        
        ' 顯示寵物的當前體力值
        UpdateEnergy()
    End Sub
    
    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        ' 執行餵食操作
        pet.Eat()
        
        ' 顯示寵物的當前體力值
        UpdateEnergy()
    End Sub
    
    Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
        ' 執行玩耍操作
        pet.Play()
        
        ' 顯示寵物的當前體力值
        UpdateEnergy()
    End Sub
    
    Private Sub UpdateEnergy()
        ' 顯示寵物的當前體力值
        Label1.Text = "當前體力值:" & pet.Energy.ToString()
    End Sub
End Class

Public Class Pet
    Protected name As String ' 寵物名字
    Protected energy As Integer ' 寵物體力值
    
    Public Sub New(ByVal name As String, ByVal initialEnergy As Integer)
        Me.name = name
        Me.energy = initialEnergy
    End Sub
    
    Public Overridable Sub Eat()
        energy += 10 ' 餵食增加體力值
    End Sub
    
    Public Overridable Sub Play()
        energy -= 5 ' 玩耍消耗體力值
    End Sub
    
    Public ReadOnly Property Energy() As Integer
        Get
            Return energy
        End Get
    End Property
End Class

Public Class Dog
    Inherits Pet
    
    Public Sub New(ByVal name As String, ByVal initialEnergy As Integer)
        MyBase.New(name, initialEnergy)
    End Sub
    
    Public Overrides Sub Eat()
        MyBase.Eat() ' 調用父類別的 Eat 方法
        energy += 5 ' 狗狗餵食額外增加 5 點體力值
    End Sub
    
    Public Overrides Sub Play()
        MyBase.Play() ' 調用父類別的 Play 方法
        energy -= 3 ' 狗狗玩耍額外消耗 3 點體力值
    End Sub
End Class

Public Class Cat
    Inherits Pet
    
    Public Sub New(ByVal name As String, ByVal initialEnergy As Integer)
        MyBase.New(name, initialEnergy)
    End Sub
    
    Public Overrides Sub Eat()
        MyBase.Eat() ' 調用父類別的 Eat 方法
        energy += 3 ' 貓咪餵食額外增加 3 點體力值
    End Sub
    
    Public Overrides Sub Play()
        MyBase.Play() ' 調用父類別的 Play 方法
        energy -= 2 ' 貓咪玩耍額外消耗 2 點體力值
    End Sub
End Class

在這個範例中,定義了四個類別:Form1PetDogCatForm1 是視窗窗體類別,包含了使用者介面的控制項和事件處理程式。Pet 是寵物的基類別,包含了寵物的共同屬性和方法。DogCatPet 的子類別,分別表示狗和貓,它們繼承了 Pet 類別,並重寫了 EatPlay 方法以實現不同的行為。

Pet 類別有一個帶有兩個參數的建構式,用於初始化寵物的名字和初始體力值。它還提供了 EatPlay 方法,分別用於執行餵食和玩耍操作,這些方法在子類別中被重寫以實現不同的行為。Energy 屬性是一個唯讀屬性,用於獲取寵物的當前體力值。

DogCat 類別的建構式調用了父類別的建構式,並在 EatPlay 方法中調用父類別的對應方法,同時額外增加或減少了一些體力值,以表現出不同寵物的特性。

Form1 類別中,宣告了一個 Pet 類型的變數 pet。在窗體載入時,在下拉式選單中添加了寵物類型的選項。當使用者點擊 Button1 時,根據使用者選擇的寵物類型、輸入的名字和初始體力值創建對應的寵物物件,並將其賦值給 pet 變數。

當使用者點擊 Button2Button3 時,分別調用 pet 物件的 EatPlay 方法來執行相應的操作。在每次操作後,都調用 UpdateEnergy 方法來更新並顯示寵物的當前體力值。

UpdateEnergy 方法使用 pet.Energy 屬性獲取寵物的當前體力值,並將其顯示在 Label1 控制項中。

透過這個範例,展示了如何使用建構式和繼承來創建和初始化不同類型的寵物物件,並將物件與使用者介面進行互動。使用者可以選擇寵物類型,輸入寵物的名字和初始體力值,執行餵食和玩耍操作,並即時查看寵物的體力值變化。