VB.NET 物件 (Object) 筆記 (基礎篇)
物件的本質
物件就像是一個裝滿零件的工具箱,它將相關的資料(屬性)和功能(方法)組織在一起,形成一個獨立的實體。每個物件都有自己的獨特性,就像每個工具箱裡的工具組合都不盡相同。透過建立和使用物件,可以更有效地管理和操作程式中的資料和功能。
物件 (Object): 物件是一種將資料和功能封裝在一起的程式設計概念。它是類別 (Class) 的實例,具有狀態(屬性)和行為(方法)。
在物件導向程式設計 (OOP) 中,物件是最基本的構建單元。每個物件都有自己的身份、狀態和行為,它們可以彼此互動,完成複雜的任務。透過創建和操作物件,可以更自然地表達真實世界中的事物和概念,提高程式的可讀性、可維護性和可重用性。
物件與類別的差異
在討論物件與類別的差異之前,先想像一下,類別就像是一個蛋糕的模具,它定義了蛋糕的形狀、大小和口味等特性。而物件就像是根據這個模具烤出來的一個個蛋糕,每個蛋糕都有模具定義的特性,但又各自獨立,可以添加不同的裝飾。
現在,讓我們更詳細地探討物件與類別的差異:
定義與實例
- 類別 (Class): 類別是一種抽象的設計圖或模板,它定義了物件應該具有的屬性和方法。類別本身並不佔用內存空間,它只是一種描述。
- 物件 (Object): 物件是類別的具體實例,它是根據類別的定義創建出來的,佔用實際的內存空間。每個物件都有自己獨特的屬性值。
舉個例子:
Public Class Person
' 定義 Person 類別的屬性
Public Property Name As String
Public Property Age As Integer
End Class
' 創建兩個 Person 物件
Dim person1 As New Person With {.Name = "John", .Age = 25}
Dim person2 As New Person With {.Name = "Alice", .Age = 30}
在這個例子中,Person 是一個類別,它定義了 Name 和 Age 兩個屬性。而 person1 和 person2 是根據 Person 類別創建的兩個物件,它們有各自的名字和年齡。
關係與互動
- 類別: 類別定義了物件的屬性和方法,描述了物件應該具有的特性和行為。類別之間可以通過繼承 (Inheritance) 建立層次關係。
- 物件: 物件是類別的實例,它們可以訪問和修改自己的屬性,以及調用自己的方法。物件之間可以通過方法的調用和屬性的訪問進行互動。
舉個例子:
Public Class BankAccount
' 定義 BankAccount 類別的屬性
Public Property AccountNumber As String
Public Property Balance As Decimal
' 定義 BankAccount 類別的方法
Public Sub Deposit(amount As Decimal)
Balance += amount
End Sub
Public Sub Withdraw(amount As Decimal)
If Balance >= amount Then
Balance -= amount
Else
Throw New Exception("Insufficient balance")
End If
End Sub
End Class
' 創建兩個 BankAccount 物件
Dim account1 As New BankAccount With {.AccountNumber = "001", .Balance = 1000}
Dim account2 As New BankAccount With {.AccountNumber = "002", .Balance = 500}
' 物件之間的互動
account1.Withdraw(200)
account2.Deposit(200)
在這個例子中,BankAccount 類別定義了銀行帳戶的屬性(帳號和餘額)和方法(存款和取款)。而 account1 和 account2 是根據 BankAccount 類別創建的兩個物件,它們代表了兩個不同的銀行帳戶。透過調用物件的方法,可以在兩個帳戶之間進行轉帳。
類別是物件的藍圖或模板,定義了物件應該具有的屬性和方法;而物件是類別的具體實例,每個物件都有自己獨特的屬性值,並可以互相交互。
| 類別 (Class) | 建構函式 (Constructor) | 物件 (Object) |
|---|---|---|
| 類別是物件的藍圖或模板,定義了物件應該具有的屬性和方法。 | 建構函式是一種特殊的方法,用於在建立物件時初始化其屬性。 | 物件是類別的具體實例,根據類別的定義創建而成。 |
| 類別本身不佔用內存空間,只是一種描述。 | 建構函式與類別同名,可以接受參數。 | 每個物件都有自己獨特的屬性值,佔用實際的內存空間。 |
| 類別之間可以通過繼承 (Inheritance) 建立層次關係。 | 建構函式在創建物件時自動調用,進行必要的初始化操作。 | 物件之間可以通過方法的調用和屬性的訪問進行互動。 |
屬性和方法
物件由兩個主要部分組成:屬性(資料)和方法(功能)。
屬性 (Properties)
屬性是物件的資料或狀態,用於描述物件的特徵。例如,一個人物件可能有姓名、年齡、身高等屬性。在 VB.NET 中,可以使用 Property 關鍵字來定義屬性:
Public Class Person
Public Property Name As String
Public Property Age As Integer
Public Property Height As Double
End Class
通過設置和訪問屬性,可以讀取和修改物件的狀態。
方法 (Methods)
方法是物件的功能或行為,用於執行特定的操作。例如,一個人物件可能有說話、走路等方法。在 VB.NET 中,可以使用 Sub 或 Function 關鍵字來定義方法:
Public Class Person
Public Sub Speak(message As String)
MessageBox.Show(message)
End Sub
Public Function Walk(distance As Double) As Double
' 執行走路的操作
Return distance
End Function
End Class
通過調用方法,可以執行物件的特定行為,完成相應的任務。
建立物件
要使用物件,需要先建立它的實例。在 VB.NET 中,可以使用 New 關鍵字來建立物件:
Dim person As New Person()
建立物件後,可以訪問和修改其屬性,以及調用其方法:
person.Name = "John"
person.Age = 25
person.Height = 180.5
person.Speak("Hello, world!")
Dim distance As Double = person.Walk(10.0)
建構函式 (Constructor)
建構函式是一種特殊的方法,用於在建立物件時初始化其屬性。它與類別同名,可以接受參數。例如:
Public Class Person
Public Sub New(name As String, age As Integer, height As Double)
Me.Name = name
Me.Age = age
Me.Height = height
End Sub
End Class
使用帶參數的建構函式建立物件:
Dim person As New Person("John", 25, 180.5)
物件之間的互動
物件可以彼此互動,透過方法和屬性的調用,實現複雜的功能。以下是一個範例,演示了兩個物件之間的互動:
所需元件:
- Button1:用於觸發物件互動的按鈕
- Label1:用於顯示互動結果的標籤
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
' 建立兩個物件
Dim calculator As New Calculator()
Dim printer As New ResultPrinter()
' 物件之間的互動
Dim result As Double = calculator.Add(10, 20)
printer.PrintResult(result)
End Sub
End Class
Public Class Calculator
Public Function Add(a As Double, b As Double) As Double
Return a + b
End Function
End Class
Public Class ResultPrinter
Public Sub PrintResult(result As Double)
' 將結果顯示在 Label1 上
Form1.Label1.Text = "Result: " & result.ToString()
End Sub
End Class
在這個範例中,會建立兩個物件:Calculator 和 ResultPrinter。Calculator 物件提供了一個 Add 方法,用於執行加法運算;ResultPrinter 物件提供了一個 PrintResult 方法,用於將結果顯示在 Label1 上。透過物件之間的互動,可以將計算結果從 Calculator 物件傳遞到 ResultPrinter 物件,並最終顯示在使用者介面上。
使用物件的優勢
使用物件有以下優勢:
| 優勢 | 說明 |
|---|---|
| 封裝性 | 將資料和功能封裝在物件中,隱藏內部細節,提高安全性和可維護性。 |
| 模組化 | 將程式分解為獨立的物件,提高程式的模組化程度,便於開發和維護。 |
| 可重用性 | 物件可以被多次使用,提高程式的可重用性,減少重複編碼。 |
| 可讀性 | 使用物件可以更自然地表達真實世界中的事物和概念,提高程式的可讀性。 |
物件的使用限制
儘管物件有許多優勢,但它也有一些使用限制:
- 性能開銷:創建和銷毀物件需要一定的性能開銷,尤其是在需要大量物件的情況下。
- 內存占用:每個物件都會占用一定的內存空間,大量的物件可能會導致內存占用過高。
- 複雜度:過度使用物件可能會導致程式結構變得複雜,增加理解和維護的難度。
為了避免這些限制,應該合理設計和使用物件,避免過度設計和濫用。同時,在性能敏感的場景中,可以考慮使用其他技術,如結構體 (Structure) 或值類型 (Value Type),以減少性能開銷和內存占用。
進階用法
繼承 (Inheritance)
繼承是物件導向程式設計中的一個重要概念,它允許從現有的類別創建新的類別通過繼承,可以在現有類別的基礎上添加新的屬性和方法,或者修改現有的屬性和方法,以創建更專門化的類別。。繼承可以提高程式的可重用性和可維護性。在 VB.NET 中,可以使用 Inherits 關鍵字來實現繼承:
Public Class Animal
Public Sub Eat()
MessageBox.Show("The animal is eating.")
End Sub
End Class
Public Class Dog
Inherits Animal
Public Sub Bark()
MessageBox.Show("The dog is barking.")
End Sub
End Class
在這個範例中,Dog 類別繼承自 Animal 類別,因此 Dog 物件可以使用 Animal 類別中定義的 Eat 方法,同時也可以使用自己特有的 Bark 方法。
多型 (Polymorphism)
多型是物件導向程式設計中另一個重要概念,它允許使用通用的介面來操作不同類型的物件通過多型,可以編寫更具有通用性和可維護性的程式碼,而不必為每個特定類型的物件編寫單獨的程式碼。。在 VB.NET 中,可以使用 Overrides 關鍵字來實現多型:
Public Class Animal
Public Overridable Sub MakeSound()
MessageBox.Show("The animal makes a sound.")
End Sub
End Class
Public Class Dog
Inherits Animal
Public Overrides Sub MakeSound()
MessageBox.Show("The dog barks.")
End Sub
End Class
Public Class Cat
Inherits Animal
Public Overrides Sub MakeSound()
MessageBox.Show("The cat meows.")
End Sub
End Class
在這個範例中,Animal 類別定義了一個可重寫的 MakeSound 方法,而 Dog 和 Cat 類別分別重寫了這個方法,提供了自己特有的實現。透過多型,可以使用 Animal 類型的變數來引用 Dog 和 Cat 物件,並調用它們各自的 MakeSound 方法。
繼承和多型是物件導向程式設計中非常強大的概念,它們可以幫助設計出更加靈活、可重用、可維護的程式碼。在實際開發中,可以根據具體的需求和場景,恰當地運用這些概念,以提高程式的品質和效率。
物件在實務的應用
在實務開發中,使用物件可以使程式更加模組化、易於維護和擴展。舉個例子,就像在組裝一台電腦時,我們會將各個部件(如 CPU、記憶體、硬碟)封裝成獨立的模組,這樣可以更方便地升級和替換,而不必對整台電腦進行大規模的改動。同樣地,在軟體開發中,將複雜的系統拆分成獨立的物件,並定義它們之間的關係和互動,可以建立出更加清晰、健全的程式架構。
下面我們通過一個具體的例子,來詳細說明在開發中使用物件和不使用物件的差異。
開發一個簡單的繪圖程式
假設我們需要開發一個簡單的繪圖程式,允許使用者在畫布上繪製不同的圖形,如矩形、圓形和三角形等。每個圖形都有自己的屬性,如位置、大小和顏色等。
如果不使用物件,我們可能需要為每種圖形定義單獨的變數和函數,例如:
Public Class Form1
Dim rectX, rectY, rectWidth, rectHeight As Integer
Dim circleX, circleY, circleRadius As Integer
Dim triangleX1, triangleY1, triangleX2, triangleY2, triangleX3, triangleY3 As Integer
Private Sub DrawRectangle(x As Integer, y As Integer, width As Integer, height As Integer)
' 繪製矩形的程式碼...
End Sub
Private Sub DrawCircle(x As Integer, y As Integer, radius As Integer)
' 繪製圓形的程式碼...
End Sub
Private Sub DrawTriangle(x1 As Integer, y1 As Integer, x2 As Integer, y2 As Integer, x3 As Integer, y3 As Integer)
' 繪製三角形的程式碼...
End Sub
End Class
這種方式的問題在於,每添加一種新的圖形,就需要定義一組新的變數和函數,程式會變得越來越龐大和難以維護。而且,如果需要為圖形添加新的屬性(如填充模式),就必須修改所有相關的變數和函數,非常容易出錯。
而使用物件則可以將不同圖形的共同特徵抽象成一個基類 Shape,並為每種具體的圖形建立一個衍生類:
Public MustInherit Class Shape
' 定義圖形的共同屬性
Public Property X As Integer
Public Property Y As Integer
Public Property Color As Color
' 定義圖形的共同方法(抽象方法)
Public MustOverride Sub Draw(graphics As Graphics)
End Class
Public Class Rectangle
Inherits Shape
' 定義矩形特有的屬性
Public Property Width As Integer
Public Property Height As Integer
' 實作矩形的繪製方法
Public Overrides Sub Draw(graphics As Graphics)
graphics.FillRectangle(New SolidBrush(Color), X, Y, Width, Height)
End Sub
End Class
Public Class Circle
Inherits Shape
' 定義圓形特有的屬性
Public Property Radius As Integer
' 實作圓形的繪製方法
Public Overrides Sub Draw(graphics As Graphics)
graphics.FillEllipse(New SolidBrush(Color), X - Radius, Y - Radius, Radius * 2, Radius * 2)
End Sub
End Class
使用這種物件導向的設計,每種圖形都是一個獨立的類別,包含了圖形特有的屬性和繪製方法。這樣一來,只需要為每種新的圖形建立一個新的類別,而不必修改現有的程式碼。同時,如果需要為所有圖形添加新的屬性或方法,只需要在基類 Shape 中進行修改即可,所有衍生類都會自動繼承這些改動。
在使用時,我們只需要根據需要建立不同圖形的物件,並呼叫它們的 Draw 方法即可:
Public Class Form1
' 宣告一個 List 來儲存所有的圖形物件
Private shapes As New List(Of Shape)
' 在表單的 Paint 事件中繪製所有圖形
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
For Each shape In shapes
shape.Draw(e.Graphics)
Next
End Sub
' 在表單的 Load 事件中建立一些範例圖形物件
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' 建立一個矩形物件,設定其屬性,並加入到 shapes 列表中
shapes.Add(New Rectangle With {.X = 50, .Y = 50, .Width = 100, .Height = 50, .Color = Color.Red})
' 建立一個圓形物件,設定其屬性,並加入到 shapes 列表中
shapes.Add(New Circle With {.X = 150, .Y = 100, .Radius = 30, .Color = Color.Blue})
' 建立更多圖形物件...
End Sub
End Class
這種基於物件的設計使得程式更加模組化、易於維護和擴展。當需要添加新的圖形時,只需要建立一個新的類別,繼承自 Shape 基類,並實作特定的繪製邏輯。而且,所有圖形的共同屬性和方法都在基類中定義,避免了程式碼的重複和不一致。