VB.NET 物件(Object) 筆記(基礎篇)
Object 是依照類別建立出來的實際資料實體。類別負責定義規格,物件則真正保存資料並執行方法。程式在執行期間操作的,通常不是抽象的類別,而是一個一個已建立的物件。
理解物件時,重點是看見「每個物件都有自己的狀態」。相同類別可以建立多個物件,但每個物件保存的資料可以不同;方法執行時,也會依照該物件目前的狀態得到不同結果。
先理解物件是什麼
物件是有狀態、能執行方法的實體
物件不是單純的變數集合。它同時包含目前資料與可執行的行為。例如一盞桌燈物件可以記錄亮度、是否開啟,也可以執行開燈、關燈、調整亮度等方法。
- 狀態:物件目前保存的資料,例如名稱、數量、亮度、餘額。
- 行為:物件可以執行的方法,例如加點數、扣款、改狀態、建立顯示文字。
- 獨立性:同一個類別建立出的不同物件,彼此有各自的資料。
- 參考:物件變數通常保存的是物件參考,不是把整個物件內容複製一份。
物件基礎篇要先掌握四個問題:
- 物件從哪裡來:通常使用
New依照類別建立。 - 物件保存什麼:屬性與欄位保存物件目前的狀態。
- 物件能做什麼:方法讓物件依照自己的狀態執行行為。
- 物件如何互動:一個物件可以把資料交給另一個物件處理。
物件與類別的差異
| 比較項目 | 類別 Class | 物件 Object |
|---|---|---|
| 角色 | 定義規格。 | 依照規格建立出的實體。 |
| 是否有實際資料 | 描述有哪些資料欄位。 | 保存每個欄位的實際值。 |
| 數量 | 通常一種概念設計一個類別。 | 可建立很多個物件。 |
| 範例 | DeskLamp |
書桌燈、床頭燈、展示燈。 |
場景一:同一個類別建立兩盞不同桌燈
這個範例用桌燈來示範物件獨立性。兩個物件都來自 DeskLamp 類別,但名稱、亮度與開關狀態不同。
需要的主控項
ButtonShow:顯示兩盞桌燈狀態。ListBoxResult:列出物件資料。
範例程式碼
VB.NET / Windows Forms
Public Class DeskLamp
Public Property LampName As String
Public Property Brightness As Integer
Public Property IsTurnedOn As Boolean
Public Sub New(ByVal lampName As String,
ByVal brightness As Integer,
ByVal isTurnedOn As Boolean)
Me.LampName = lampName
Me.Brightness = brightness
Me.IsTurnedOn = isTurnedOn
End Sub
Public Function BuildStatusText() As String
Dim powerText As String = If(IsTurnedOn, "開啟", "關閉")
Return LampName & "|" & powerText & "|亮度 " & Brightness.ToString()
End Function
End Class
Public Class Form1
Private Sub ButtonShow_Click(sender As Object, e As EventArgs) Handles ButtonShow.Click
Dim readingLamp As New DeskLamp("閱讀燈", 80, True)
Dim nightLamp As New DeskLamp("夜燈", 20, False)
ListBoxResult.Items.Clear()
ListBoxResult.Items.Add(readingLamp.BuildStatusText())
ListBoxResult.Items.Add(nightLamp.BuildStatusText())
End Sub
End Class
畫面輸出結果(ListBoxResult)
閱讀燈|開啟|亮度 80
夜燈|關閉|亮度 20邏輯解析
DeskLamp是類別,負責定義桌燈有哪些資料與方法。readingLamp與nightLamp是兩個不同物件。- 兩個物件使用相同方法,但輸出會依照各自狀態不同而不同。
物件狀態與方法
屬性保存狀態,方法改變或使用狀態
物件真正有感的地方,是狀態會改變。方法可以讀取目前狀態,也可以在符合規則時修改狀態。這讓物件不只是資料容器,而是能維護自身規則的單位。
場景二:水壺物件記錄目前水量
這個範例用水壺示範物件狀態。每次按下喝水按鈕,水壺的目前水量會減少;若水量不足,方法會回傳失敗。
需要的主控項
TextBoxDrinkAmount:輸入要喝掉的毫升數。ButtonDrink:執行喝水。ButtonRefill:補滿水壺。LabelStatus:顯示水壺狀態。
範例程式碼
VB.NET / Windows Forms
Public Class WaterBottle
Public ReadOnly Property CapacityMl As Integer
Public Property CurrentMl As Integer
Public Sub New(ByVal capacityMl As Integer)
Me.CapacityMl = capacityMl
Me.CurrentMl = capacityMl
End Sub
Public Function Drink(ByVal amountMl As Integer) As Boolean
If amountMl <= 0 Then
Return False
End If
If amountMl > CurrentMl Then
Return False
End If
CurrentMl -= amountMl
Return True
End Function
Public Sub Refill()
CurrentMl = CapacityMl
End Sub
Public Function BuildStatusText() As String
Return "目前水量:" & CurrentMl.ToString() & " / " & CapacityMl.ToString() & " ml"
End Function
End Class
Public Class Form1
Private bottle As New WaterBottle(600)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
LabelStatus.Text = bottle.BuildStatusText()
End Sub
Private Sub ButtonDrink_Click(sender As Object, e As EventArgs) Handles ButtonDrink.Click
Dim amount As Integer
If Not Integer.TryParse(TextBoxDrinkAmount.Text.Trim(), amount) Then
LabelStatus.Text = "請輸入正確毫升數"
Return
End If
If bottle.Drink(amount) Then
LabelStatus.Text = bottle.BuildStatusText()
Else
LabelStatus.Text = "水量不足或數值不正確|" & bottle.BuildStatusText()
End If
End Sub
Private Sub ButtonRefill_Click(sender As Object, e As EventArgs) Handles ButtonRefill.Click
bottle.Refill()
LabelStatus.Text = bottle.BuildStatusText()
End Sub
End Class
畫面輸出結果(TextBoxDrinkAmount = 180)
目前水量:420 / 600 ml邏輯解析
bottle是表單中保存的水壺物件。Drink會依照目前水量決定是否可以扣除。CurrentMl會隨著方法執行而改變,這就是物件狀態變化。
物件變數與參考
場景三:兩個變數指向同一個便當物件
物件變數保存的是參考。若兩個變數指向同一個物件,透過其中一個變數修改狀態,另一個變數看到的也會是修改後的結果。
需要的主控項
ButtonTestReference:測試物件參考。TextBoxLog:顯示前後變化,建議設定Multiline=True。
範例程式碼
VB.NET / Windows Forms
Public Class LunchBox
Public Property BoxName As String
Public Property IsPickedUp As Boolean
Public Sub New(ByVal boxName As String)
Me.BoxName = boxName
Me.IsPickedUp = False
End Sub
Public Sub MarkPickedUp()
IsPickedUp = True
End Sub
Public Function BuildText() As String
Dim statusText As String = If(IsPickedUp, "已領取", "尚未領取")
Return BoxName & "|" & statusText
End Function
End Class
Public Class Form1
Private Sub ButtonTestReference_Click(sender As Object, e As EventArgs) Handles ButtonTestReference.Click
TextBoxLog.Multiline = True
TextBoxLog.Clear()
Dim frontDeskBox As New LunchBox("雞腿便當 A12")
Dim kitchenRecord As LunchBox = frontDeskBox
TextBoxLog.AppendText("修改前:" & kitchenRecord.BuildText() & Environment.NewLine)
frontDeskBox.MarkPickedUp()
TextBoxLog.AppendText("修改後:" & kitchenRecord.BuildText() & Environment.NewLine)
End Sub
End Class
畫面輸出結果(TextBoxLog)
修改前:雞腿便當 A12|尚未領取
修改後:雞腿便當 A12|已領取邏輯解析
frontDeskBox與kitchenRecord指向同一個LunchBox物件。- 透過
frontDeskBox.MarkPickedUp()修改狀態後,kitchenRecord看到的狀態也會改變。 - 這是物件參考的基本特性,不是複製出另一份便當資料。
參考特性需要留意。 若需要兩份彼此獨立的資料,必須建立兩個物件。只把物件指定給另一個變數,通常只是多一個變數指向同一個物件。
物件之間的互動
場景四:點餐物件交給取餐叫號物件處理
實務上常見的設計不是讓一個物件做完所有事情,而是讓不同物件負責不同工作。這個範例中,點餐物件保存餐點資料,叫號物件負責產生顯示文字。
需要的主控項
ButtonMakeTicket:產生取餐號碼。LabelTicket:顯示取餐資訊。
範例程式碼
VB.NET / Windows Forms
Public Class MealOrder
Public Property OrderNo As String
Public Property MealName As String
Public Property DrinkName As String
Public Sub New(ByVal orderNo As String,
ByVal mealName As String,
ByVal drinkName As String)
Me.OrderNo = orderNo
Me.MealName = mealName
Me.DrinkName = drinkName
End Sub
End Class
Public Class PickupTicketPrinter
Public Function BuildTicketText(ByVal order As MealOrder) As String
Return "取餐號 " & order.OrderNo & "|" &
order.MealName & " + " & order.DrinkName
End Function
End Class
Public Class Form1
Private Sub ButtonMakeTicket_Click(sender As Object, e As EventArgs) Handles ButtonMakeTicket.Click
Dim order As New MealOrder("B-27", "番茄起司貝果", "無糖紅茶")
Dim printer As New PickupTicketPrinter()
LabelTicket.Text = printer.BuildTicketText(order)
End Sub
End Class
畫面輸出結果(LabelTicket.Text)
取餐號 B-27|番茄起司貝果 + 無糖紅茶邏輯解析
MealOrder專心保存點餐資料。PickupTicketPrinter專心產生取餐顯示文字。- 物件互動的重點是分工,而不是把所有邏輯都塞進單一物件。
多個物件的集合管理
場景五:管理閱讀座位清單
當需要管理多筆同類型資料時,可使用 List(Of T) 保存多個物件。這個範例用閱讀座位示範:每個座位都是一個物件,清單負責保存全部座位。
需要的主控項
ButtonShowSeats:顯示座位清單。ListBoxSeats:列出座位狀態。
範例程式碼
VB.NET / Windows Forms
Public Class ReadingSeat
Public Property SeatCode As String
Public Property UserName As String
Public Property IsReserved As Boolean
Public Sub New(ByVal seatCode As String,
ByVal userName As String,
ByVal isReserved As Boolean)
Me.SeatCode = seatCode
Me.UserName = userName
Me.IsReserved = isReserved
End Sub
Public Function BuildDisplayText() As String
If IsReserved Then
Return SeatCode & "|已預約|" & UserName
End If
Return SeatCode & "|可使用"
End Function
End Class
Public Class Form1
Private seats As New List(Of ReadingSeat)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
seats.Add(New ReadingSeat("A01", "許同學", True))
seats.Add(New ReadingSeat("A02", "", False))
seats.Add(New ReadingSeat("B05", "吳同學", True))
End Sub
Private Sub ButtonShowSeats_Click(sender As Object, e As EventArgs) Handles ButtonShowSeats.Click
ListBoxSeats.Items.Clear()
For Each seat As ReadingSeat In seats
ListBoxSeats.Items.Add(seat.BuildDisplayText())
Next
End Sub
End Class
畫面輸出結果(ListBoxSeats)
A01|已預約|許同學
A02|可使用
B05|已預約|吳同學邏輯解析
ReadingSeat代表一個座位物件。seats是保存多個座位物件的清單。- 每個座位物件都能依照自己的狀態產生不同顯示文字。
繼承與多型入門
場景六:不同提醒物件用相同方式顯示
多型的基本感覺是:用相同方法呼叫不同物件,結果會依照物件實際型別而不同。這個範例用一般提醒與倒數提醒示範。
需要的主控項
ButtonShowReminders:顯示提醒清單。ListBoxReminders:列出提醒內容。
範例程式碼
VB.NET / Windows Forms
Public Class ReminderBase
Public Property Title As String
Public Sub New(ByVal title As String)
Me.Title = title
End Sub
Public Overridable Function BuildText() As String
Return "提醒:" & Title
End Function
End Class
Public Class CountdownReminder
Inherits ReminderBase
Public Property MinutesLeft As Integer
Public Sub New(ByVal title As String, ByVal minutesLeft As Integer)
MyBase.New(title)
Me.MinutesLeft = minutesLeft
End Sub
Public Overrides Function BuildText() As String
Return "倒數 " & MinutesLeft.ToString() & " 分鐘:" & Title
End Function
End Class
Public Class Form1
Private Sub ButtonShowReminders_Click(sender As Object, e As EventArgs) Handles ButtonShowReminders.Click
Dim reminders As New List(Of ReminderBase) From {
New ReminderBase("帶識別證"),
New CountdownReminder("線上會議開始", 15),
New CountdownReminder("午餐預訂截止", 5)
}
ListBoxReminders.Items.Clear()
For Each reminder As ReminderBase In reminders
ListBoxReminders.Items.Add(reminder.BuildText())
Next
End Sub
End Class
畫面輸出結果(ListBoxReminders)
提醒:帶識別證
倒數 15 分鐘:線上會議開始
倒數 5 分鐘:午餐預訂截止邏輯解析
ReminderBase提供共同的提醒格式。CountdownReminder繼承基底類別並覆寫BuildText()。List(Of ReminderBase)可同時管理一般提醒與倒數提醒。- 同樣呼叫
BuildText(),會依照物件實際型別產生不同文字。
使用物件的實務判斷
常見誤區
- 只把物件當成變數袋:只有資料沒有方法,邏輯仍散在表單中。
- 每件小事都硬拆物件:問題很小時,過度拆分會讓閱讀成本上升。
- 忘記物件參考特性:多個變數可能指向同一個物件,修改後會互相影響。
- 表單做太多事:Form 同時處理輸入、資料規則、顯示格式與集合管理。
| 判斷點 | 適合用物件 | 不一定需要物件 |
|---|---|---|
| 資料是否有結構 | 同一筆資料包含多個欄位,例如座位、訂單、提醒。 | 只有單一簡單值,例如一個計數器。 |
| 是否有狀態變化 | 資料會被方法更新,例如水量、領取狀態、預約狀態。 | 只做一次性計算且不保存狀態。 |
| 是否有多筆資料 | 需要用 List(Of T) 管理多個同類型實體。 |
只有單筆臨時資料且不重複使用。 |
| 是否需要分工 | 資料保存、格式輸出、規則判斷可分給不同物件。 | 畫面事件中只有一兩行簡單顯示。 |
重點整理
- 物件是依照類別建立出來的實際實體。
- 物件包含狀態與行為;狀態保存在屬性或欄位中,行為由方法提供。
- 同一個類別可以建立多個物件,每個物件有自己的資料。
- 物件變數通常保存參考;兩個變數可能指向同一個物件。
- 物件方法可以依照目前狀態改變結果,例如扣水量、標記領取、建立顯示文字。
List(Of T)可用來管理多個同類型物件。- 多型讓不同物件用相同方法呼叫時,產生符合自身型別的結果。
- Windows Forms 中,表單適合處理輸入與顯示,物件適合保存資料、規則與行為。