VB.NET 類別(Class) 筆記(核心篇)
Class 是用來定義「一種資料結構與對應行為」的語法。資料放在屬性裡,行為放在方法裡;建立物件後,每個物件都可以保存自己的資料,並使用類別定義好的方法處理這些資料。
類別的重點不是把程式碼隨便包起來,而是讓資料、規則與操作有清楚的位置。Windows Forms 中若所有邏輯都塞進按鈕事件,程式很快會變得難讀;把資料與計算搬進類別後,表單可以專心處理輸入與顯示。
先理解類別與物件
類別定義規格,物件保存實際資料
類別可以理解成一種資料規格。它描述一筆資料應該有哪些欄位、可以做哪些操作。物件則是依照這份規格建立出來的實際資料。
- 類別(Class):定義資料與行為的規格。
- 物件(Object):依照類別建立出來的實際實例。
- 屬性(Property):物件保存的資料,例如名稱、數量、價格。
- 方法(Method):物件可以執行的動作,例如計算、格式化、判斷狀態。
類別適合解決三種問題:
- 資料分散:同一筆資料拆成很多變數,讀起來沒有整體感。
- 邏輯重複:相同計算一直寫在不同按鈕事件中。
- 表單太重:Form 同時負責輸入、計算、判斷、格式化與顯示。
| 項目 | 類別 | 物件 |
|---|---|---|
| 定位 | 定義資料格式與可用方法。 | 依照類別建立出的實際資料。 |
| 範例 | MemberCard |
一張具體會員卡。 |
| 資料 | 宣告有哪些屬性。 | 每個屬性有自己的實際值。 |
| 數量 | 通常一種概念設計一個類別。 | 可建立很多個物件。 |
基本語法與成員
類別基本結構
一個類別通常會包含屬性、建構函式與方法。屬性保存資料,建構函式負責建立時的初始設定,方法負責處理行為。
VB.NET
Public Class 類別名稱
Public Property 屬性名稱 As 資料型別
Public Sub New()
' 建立物件時執行
End Sub
Public Function 方法名稱() As 回傳型別
' 執行某段行為
End Function
End Class
| 成員 | 用途 | 常見寫法 |
|---|---|---|
| Property | 讓外部讀取或設定資料。 | Public Property Name As String |
| Private Field | 只在類別內部保存資料。 | Private _balance As Decimal |
| Sub | 執行動作,不回傳值。 | Public Sub AddPoint() |
| Function | 執行動作,並回傳結果。 | Public Function GetTotal() As Decimal |
| Constructor | 建立物件時設定初始值。 | Public Sub New(...) |
基礎使用:建立物件與顯示資料
場景一:建立會員卡物件
這個範例用會員卡作為情境。類別負責保存會員姓名、等級與點數,表單只負責建立物件並顯示摘要。
需要的主控項
ButtonCreate:建立會員卡。LabelResult:顯示會員摘要。
範例程式碼
VB.NET / Windows Forms
Public Class MemberCard
Public Property MemberName As String
Public Property LevelName As String
Public Property PointBalance As Integer
Public Sub New(ByVal memberName As String,
ByVal levelName As String,
ByVal pointBalance As Integer)
Me.MemberName = memberName
Me.LevelName = levelName
Me.PointBalance = pointBalance
End Sub
Public Function BuildSummary() As String
Return MemberName & "|" & LevelName & "|剩餘點數:" & PointBalance.ToString()
End Function
End Class
Public Class Form1
Private Sub ButtonCreate_Click(sender As Object, e As EventArgs) Handles ButtonCreate.Click
Dim card As New MemberCard("林宜真", "金卡會員", 1280)
LabelResult.Text = card.BuildSummary()
End Sub
End Class
畫面輸出結果(LabelResult.Text)
林宜真|金卡會員|剩餘點數:1280邏輯解析
MemberCard定義會員卡需要的資料與摘要格式。New MemberCard(...)建立一個實際會員卡物件。BuildSummary()把摘要格式留在類別內,避免表單事件塞滿字串組合。
場景二:用屬性與方法計算購物車金額
屬性用來保存資料,方法用來處理計算。這個範例把商品單價、數量與折扣封裝在同一個類別中,總金額由類別自己計算。
需要的主控項
TextBoxPrice:輸入單價。TextBoxQuantity:輸入數量。ButtonCalculate:計算總金額。LabelResult:顯示計算結果。
範例程式碼
VB.NET / Windows Forms
Public Class CartLine
Public Property ProductName As String
Public Property UnitPrice As Decimal
Public Property Quantity As Integer
Public Sub New(ByVal productName As String,
ByVal unitPrice As Decimal,
ByVal quantity As Integer)
Me.ProductName = productName
Me.UnitPrice = unitPrice
Me.Quantity = quantity
End Sub
Public Function GetSubtotal() As Decimal
Return UnitPrice * Quantity
End Function
Public Function BuildReceiptLine() As String
Return ProductName & " x " & Quantity.ToString() &
",小計:" & GetSubtotal().ToString("N0") & " 元"
End Function
End Class
Public Class Form1
Private Sub ButtonCalculate_Click(sender As Object, e As EventArgs) Handles ButtonCalculate.Click
Dim price As Decimal
Dim quantity As Integer
If Not Decimal.TryParse(TextBoxPrice.Text.Trim(), price) OrElse price <= 0D Then
LabelResult.Text = "單價格式錯誤"
Return
End If
If Not Integer.TryParse(TextBoxQuantity.Text.Trim(), quantity) OrElse quantity <= 0 Then
LabelResult.Text = "數量格式錯誤"
Return
End If
Dim item As New CartLine("藍牙滑鼠", price, quantity)
LabelResult.Text = item.BuildReceiptLine()
End Sub
End Class
畫面輸出結果(TextBoxPrice = 690,TextBoxQuantity = 3)
藍牙滑鼠 x 3,小計:2,070 元邏輯解析
CartLine代表購物車中的一筆商品。GetSubtotal()專門負責小計計算。- 表單負責檢查輸入與顯示結果,商品計算邏輯留在類別內。
封裝:讓資料有保護規則
場景三:儲值卡不能讓餘額變成負數
封裝的重點不是把資料藏起來,而是讓資料只能透過合理規則被修改。這個範例用儲值卡示範:餘額不能由外部隨便改,只能透過儲值與扣款方法變動。
需要的主控項
TextBoxAmount:輸入扣款金額。ButtonPay:執行扣款。LabelResult:顯示扣款結果。
範例程式碼
VB.NET / Windows Forms
Public Class StoredValueCard
Private _balance As Decimal
Public ReadOnly Property Balance As Decimal
Get
Return _balance
End Get
End Property
Public Sub New(ByVal openingBalance As Decimal)
If openingBalance < 0D Then
Throw New ArgumentException("初始餘額不可小於 0。")
End If
_balance = openingBalance
End Sub
Public Function Pay(ByVal amount As Decimal) As Boolean
If amount <= 0D Then
Return False
End If
If amount > _balance Then
Return False
End If
_balance -= amount
Return True
End Function
End Class
Public Class Form1
Private card As New StoredValueCard(500D)
Private Sub ButtonPay_Click(sender As Object, e As EventArgs) Handles ButtonPay.Click
Dim amount As Decimal
If Not Decimal.TryParse(TextBoxAmount.Text.Trim(), amount) Then
LabelResult.Text = "金額格式錯誤"
Return
End If
If card.Pay(amount) Then
LabelResult.Text = "扣款成功,剩餘:" & card.Balance.ToString("N0") & " 元"
Else
LabelResult.Text = "扣款失敗,餘額:" & card.Balance.ToString("N0") & " 元"
End If
End Sub
End Class
畫面輸出結果(TextBoxAmount = 620)
扣款失敗,餘額:500 元邏輯解析
_balance是Private,外部不能直接亂改餘額。Balance是唯讀屬性,只允許外部查看餘額。Pay集中管理扣款規則,避免餘額被扣成負數。
集合物件:管理多筆資料
場景四:用類別整理待辦清單
多筆資料若只用多個陣列保存,容易發生名稱、日期、狀態對不起來的問題。用類別建立單筆資料,再用 List(Of T) 管理多筆資料,結構會更清楚。
需要的主控項
ButtonShowTasks:顯示待辦清單。ListBoxTasks:列出待辦項目。
範例程式碼
VB.NET / Windows Forms
Public Class TaskItem
Public Property Title As String
Public Property DueDate As Date
Public Property IsDone As Boolean
Public Sub New(ByVal title As String,
ByVal dueDate As Date,
ByVal isDone As Boolean)
Me.Title = title
Me.DueDate = dueDate
Me.IsDone = isDone
End Sub
Public Function BuildDisplayText() As String
Dim statusText As String = If(IsDone, "已完成", "未完成")
Return DueDate.ToString("MM/dd") & "|" & statusText & "|" & Title
End Function
End Class
Public Class Form1
Private tasks As New List(Of TaskItem)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
tasks.Add(New TaskItem("整理月報資料", Date.Today.AddDays(1), False))
tasks.Add(New TaskItem("確認會議室設備", Date.Today.AddDays(2), True))
tasks.Add(New TaskItem("寄出課程通知", Date.Today.AddDays(3), False))
End Sub
Private Sub ButtonShowTasks_Click(sender As Object, e As EventArgs) Handles ButtonShowTasks.Click
ListBoxTasks.Items.Clear()
For Each task As TaskItem In tasks
ListBoxTasks.Items.Add(task.BuildDisplayText())
Next
End Sub
End Class
畫面輸出結果(ListBoxTasks)
04/26|未完成|整理月報資料
04/27|已完成|確認會議室設備
04/28|未完成|寄出課程通知邏輯解析
TaskItem代表一筆待辦資料。List(Of TaskItem)讓多筆待辦以同一種結構保存。BuildDisplayText()統一處理顯示格式,避免表單重複組字串。
繼承與覆寫
場景五:不同通知使用不同顯示文字
繼承適合用在「有共同基礎,但每種子類別又有差異」的情境。這個範例中,一般通知與緊急通知都有標題與內容,但顯示文字不同。
需要的主控項
ButtonShowNotice:顯示通知清單。ListBoxNotice:列出通知文字。
範例程式碼
VB.NET / Windows Forms
Public Class NoticeBase
Public Property Title As String
Public Property Message As String
Public Sub New(ByVal title As String, ByVal message As String)
Me.Title = title
Me.Message = message
End Sub
Public Overridable Function BuildText() As String
Return Title & ":" & Message
End Function
End Class
Public Class UrgentNotice
Inherits NoticeBase
Public Sub New(ByVal title As String, ByVal message As String)
MyBase.New(title, message)
End Sub
Public Overrides Function BuildText() As String
Return "【緊急】" & Title & ":" & Message
End Function
End Class
Public Class Form1
Private Sub ButtonShowNotice_Click(sender As Object, e As EventArgs) Handles ButtonShowNotice.Click
Dim notices As New List(Of NoticeBase) From {
New NoticeBase("系統公告", "今晚 8 點例行維護"),
New UrgentNotice("庫存警示", "A 區耗材低於安全量")
}
ListBoxNotice.Items.Clear()
For Each notice As NoticeBase In notices
ListBoxNotice.Items.Add(notice.BuildText())
Next
End Sub
End Class
畫面輸出結果(ListBoxNotice)
系統公告:今晚 8 點例行維護
【緊急】庫存警示:A 區耗材低於安全量邏輯解析
NoticeBase定義共同資料與基本顯示格式。UrgentNotice使用Inherits繼承共同資料。Overrides改寫顯示文字,形成不同通知樣式。List(Of NoticeBase)可以同時放入一般通知與緊急通知,這就是多型的基本效果。
繼承不要過早使用。 若只是想共用幾行程式,不一定要建立繼承階層。類別之間真的有「共同基礎 + 子類差異」時,再使用繼承會比較清楚。
實務判斷與常見誤區
常見問題整理
- Form 太肥:所有計算、格式化、資料判斷都寫在按鈕事件。
- 類別只放資料:沒有把對應行為放進類別,導致邏輯仍分散在表單。
- 全部都 Public:外部可隨意修改內部狀態,封裝失去效果。
- 過早繼承:只是想共用程式碼就建立父類別,反而增加結構負擔。
- 命名不清:類別名稱看不出責任,例如
DataManager、Helper過度泛用。
| 判斷問題 | 適合放在 Form | 適合放在 Class |
|---|---|---|
| 輸入讀取 | 讀取 TextBox、ComboBox、CheckBox。 | 通常不放控制項本身。 |
| 資料計算 | 只呼叫計算方法並顯示結果。 | 金額、點數、狀態、規則判斷。 |
| 顯示格式 | 把結果放到 Label 或 ListBox。 | 建立摘要文字、狀態文字、報表列文字。 |
| 資料集合 | 觸發顯示、清空畫面。 | 單筆資料結構、多筆資料管理。 |
重點整理
Class用來定義資料與行為的結構。- 物件是依照類別建立出來的實際實例,每個物件可保存自己的資料。
- 屬性負責資料存取,方法負責行為與計算。
- 建構函式可在建立物件時設定必要初始值。
- 封裝可避免外部任意修改重要資料,讓修改流程經過規則控管。
List(Of T)搭配類別,適合管理多筆同結構資料。- 繼承適合共同基礎明確、子類差異清楚的情境,不宜過早濫用。
- Windows Forms 中,表單適合處理輸入與顯示,資料規則與計算適合交給類別。