VB.Net中文教程(1) 類別與封裝性 (轉)

worldblog發表於2007-12-06
VB.Net中文教程(1) 類別與封裝性 (轉)[@more@]

請注意 ......
著作權所有人:物澤事業股份有限公司、
  MISOO技術顧問團隊、物件導向雜誌作者、等。
u本摘自 物件導向雜誌、精通物件觀念與技術等書籍著作。
u本檔案僅供您的參閱,請遵守著作權法,不得做其它商業用途。

 

主題:  類別與封裝性(Ecapsulation)

 

????????????  內容  ????????????
v 1. 類別的「成員」
v 2. 「封裝性」概念

 


1. 類別的「程式成員」(Procedure Member)

  類別 (Class)之任務是把資料(Data)和程式(Procedure)組織並封裝起來。類別告訴計算機﹕「其物件應含有那些資料、應含有那些程式裨處理外界傳來之訊息」。類別須詳細說明它的資料及程式﹐我們稱此資料是類別之「資料成員」(Data Member) ﹔而稱此程式是類別之「程式成員」(Procedure Member)。有關類別內容之敘述﹐就是所謂的類別定義(Class Definition)。類別定義之格式為──
 
類別之用途為﹕宣告物件。例如﹕

'ex01.bas
Imports System.ComponentModel
Imports System.Drawing
Imports System.s
'----------------------------------------------------
Class Tree
  Public varity As String
  Public age As Integer
  Public height As Single
End Class
'-----------------------------------------------------
Public Class Form1
  Inherits System.WinForms.Form
 
  Public Sub New()
  MyBase.New()
  Form1 = Me
  'This call is required by the Win FoDesigner.
  InitializeComponent()
  'TODO:Add any initialization after the InitializeComponent() call
  End Sub
  'Form overrs dispose to clean up the component list.
  Public Overrides Sub Dispose()
  MyBase.Dispose()
  components.Dispose()
  End Sub
#Region " Form Designer generated code "
  .......
#End Region
  Protected Sub Form1_Click(ByVal sender As , ByVal
  e As System.EventArgs)
  Dim a As New Tree()
  MsgBox("Object a Is Created.")
  End Sub
 End Class

此程式定義了類別Tree﹐它只含資料而無程式﹐為一「陽春型」之類別。當計算機到Form1_Click()程式內之宣告指令──
  Dim a As New Tree()

就分配足夠存放這 3項資料的空間給予物件 a。然而﹐此Tree類別只有資料而無程式。所以﹐物件 a無法接受外來之訊息。此時﹐可加入程式成員﹐使Tree類別含有程式、具有動力﹐物件就有能力來處理訊息了。例如﹕

'ex02.bas
Imports System.ComponentModel
Imports System.Drawing
Imports System.WinForms
'------------------------------------------------------------
Class Tree
  Public varity As String
  Public age As Integer
  Public height As Single
  Public Sub input(ByVal hei As Single)
  height = hei
  End Sub
End Class
'------------------------------------------------------------
Public Class Form1
  Inherits System.WinForms.Form
 
  Public Sub New()
  MyBase.New()
  Form1 = Me
  'This call is required by the Win Form Designer.
  InitializeComponent()
  'TODO: Add any initialization after the InitializeComponent() call
  End Sub
  'Form overrides dispose to clean up the component list.
  Public Overrides Sub Dispose()
  MyBase.Dispose()
  components.Dispose()
  End Sub
#Region " Windows Form Designer generated code "
  ......
#End Region
  Protected Sub Form1_Click( ByVal sender As Object, ByVal
  e As System.EventArgs)
  Dim a As New Tree()
  a.input(2.1)
  Messagebox.Show("Set a.Height to 2.1", "Hello!")
  End Sub
End Class

此程式輸出:Set a.Height to 2.1
  現在﹐Tree類別已擁有程式成員 input()。程式成員的寫法與一般VB程式相同﹐只是它應宣告於類別內﹐成為類別之專屬程式。此刻﹐物件 a含有 3項資料及 1個程式﹕
 
計算機執行到指令──
  a.input(2.1)

就將訊息──input(2.1)傳給物件 a。此時計算機呼叫並執行物件 a內之input() 程式。物件 a內之 input()就是定義於Tree類別內之input() ﹔於是Form1_Click()就把自變數──2.1 傳給 input()內之 hei變數。

 
 
接下來﹐敘述──
  height = hei

把 hei變數值存入物件 a之資料成員──height中。

 
 
此刻﹐物件 a對訊息之處理完成了﹐其內部資料改變了﹐亦即物件 a之內部狀態(Internal State)改變了﹔這是物件的行為之一。上述您已經會加入一個程式了﹐依同樣方法﹐繼續加入其它程式﹐讓物件的興為更多采多姿。例如﹕

'ex03.bas
Imports System.ComponentModel
Imports System.Drawing
Imports System.WinForms
'-----------------------------------------------------------------------
Class Tree
  Public varity As String
  Public age As Integer
  Public height As Single
  Public Sub input(ByVal hei As Single)
  height = hei
  End Sub
  Public Function inquireHeight() As Single
  inquireHeight = height
  End Function
End Class
'------------------------------------------------------------------------
Public Class Form1
  Inherits System.WinForms.Form
 
  Public Sub New()
  MyBase.New()
  Form1 = Me
  'This call is required by the Win Form Designer.
  InitializeComponent()
  'TODO: Add any initialization after the InitializeComponent() call
  End Sub
  'Form overrides dispose to clean up the component list.
  Public Overrides Sub Dispose()
  MyBase.Dispose()
  components.Dispose()
  End Sub
#Region " Windows Form Designer generated code "
  ........
#End Region
  Protected Sub Form1_Click( ByVal sender As Object, ByVal
  e As System.EventArgs)
  Dim a As Tree = New Tree()
  Dim h As Single
  a.input(2.1)
  h = a.inquireHeight()
  Messagebox.Show("height = " + str(h) + "公尺", "HI!")
  End Sub
End Class

此程式輸出如下﹕height = 2.1公尺
  Tree類別有2個程式成員──input() 和inquireHeight()。類別之程式成員必須與其物件配合使用。格式為﹕
 
亦即﹐必須以訊息之形式出現。例如﹕
 
 如果程式成員不與物件相配合時﹐計算機會如何處理呢﹖例如﹕

'ex04.bas
'Some Error Here !
Imports System.ComponentModel
Imports System.Drawing
Imports System.WinForms
'--------------------------------------------------------------
Class Tree
  Public varity As String
  Public age As Integer
  Public height As Single
  Public Sub input(ByVal hei As Single)
  height = hei
  End Sub
  Public Function inquireHeight() As Single
  inquireHeight = height
  End Function
End Class
'---------------------------------------------------------------
Public Class Form1
  Inherits System.WinForms.Form
 
  Public Sub New()
  MyBase.New()
  Form1 = Me
  'This call is required by the Win Form Designer.
  InitializeComponent()
  'TODO: Add any initialization after the InitializeComponent() call
  End Sub
  'Form overrides dispose to clean up the component list.
  Public Overrides Sub Dispose()
  MyBase.Dispose()
  components.Dispose()
  End Sub
#Region " Windows Form Designer generated code "
  ........
#End Region
  Protected Sub Form1_Click( ByVal sender As Object, ByVal
  e As System.EventArgs)
  Dim a As Tree = New Tree()
  Dim h As Single
  a.input(2.1)
  h = inquireHeight()
  Messagebox.Show("height = " + str(h) + "公尺", "HI!")
  End Sub
End Class

當計算機看到Form1_Click()內之指令──
  h = inquireHeight( )

它視inquireHeight()為一獨立之程式﹐與Tree類別內之inquireHeight()無關﹔於是計算機去找此inquireHeight()之定義﹐但找不著﹔所以程式錯了。因之﹐您要掌握個原則── 程式成員之唯一任務是支援物件之行為﹐必須與物件配合使用。
2. 「封裝性」概念

  物件把資料及程式組織並「封裝」(Encapsulate) 起來﹐只透過特定的方式才能使用類別之資料成員和程式成員。物件如同手提袋﹐只從固定的開口才能存取東西﹐否則您一定不敢把錢放在手提袋中。物件像一座「」保護類別中的資料﹐使其不受外界之影響。想一想我國的萬里長城可保護關內的人民﹐避免受胡人侵犯﹐但長城並非完全封閉﹐而有山海關、玉門關等出入口。物件和萬里長城之功能是一致的﹐它保護其資料成員﹐但也有正常的資料存取管道﹕以程式成員來存取資料成員。請看個程式﹕

'ex05.bas
Imports System.ComponentModel
Imports System.Drawing
Imports System.WinForms
'-------------------------------------------------------
Class Tree
  Public varity As String
  Public age As Integer
  Public height As Single
End Class
'-------------------------------------------------------
Public Class Form1
  Inherits System.WinForms.Form
 
  Public Sub New()
  MyBase.New()
  Form1 = Me
  'This call is required by the Win Form Designer.
  InitializeComponent()
  'TODO: Add any initialization after the InitializeComponent() call
  End Sub
  'Form overrides dispose to clean up the component list.
  Public Overrides Sub Dispose()
  MyBase.Dispose()
  components.Dispose()
  End Sub
#Region " Windows Form Designer generated code "
  .......
#End Region
  Protected Sub Form1_Click( ByVal sender As Object, ByVal
  e As System.EventArgs)
  Dim a As New Tree()
  a.height = 2.1
  Messagebox.Show("height = " + str(a.height) + "公尺")
  End Sub
End Class

此程式輸出如下﹕height = 2.1公尺
  此程式中﹐Tree類別含有 3個資料成員﹐即物件內含有3個資料值,此類別之程式成員能直接存取之。同時,也允許其它程式來存取資料成員之值﹐其存取格式為﹕
 
例如﹕
  a.height = 2.1

此指令把 2.1存入物件 a之height變數中。於是物件 a之內容為﹕
 
 
 
  請看個常見錯誤如下﹕

'ex06.bas
'Some Error Here!
Imports System.ComponentModel
Imports System.Drawing
Imports System.WinForms
'-------------------- ------------------------------------
Class Tree
  Public varity As String
  Public age As Integer
  Public height As Single
End Class
'--------------------------------------------------------
Public Class Form1
  Inherits System.WinForms.Form
 
  Public Sub New()
  MyBase.New()
  Form1 = Me
  'This call is required by the Win Form Designer.
  InitializeComponent()
  'TODO: Add any initialization after the InitializeComponent() call
  End Sub
  'Form overrides dispose to clean up the component list.
  Public Overrides Sub Dispose()
  MyBase.Dispose()
  components.Dispose()
  End Sub
#Region " Windows Form Designer generated code "
  .......
#End Region
  Protected Sub Form1_Click( ByVal sender As Object, ByVal
  e As System.EventArgs)
  Dim a As New Tree()
  height = 2.1
  Messagebox.Show("height = " + str(a.height) + "公尺")
  End Sub
End Class

Form1_Click()程式內之指令── height = 2.1,此height變數並未與物件配合使用﹐計算機不認為它是Tree類別之height變數。計算機視其為Form1_Click()之自動變數(Automatic Variable)﹐但卻未見到它的宣告﹐因之程式錯了﹗這是物件對其資料成員保護最松的情形﹐因為物件所屬類別(即Tree)之外的程式(如Form1_Click()程式)尚能存取資料成員的內容。就像一顆炸彈﹐除了引信管外﹐尚有許多管道可使炸彈內之化學藥品爆炸﹔您將不敢把炸彈擺在飛機上﹐因何時會爆炸將無法控制。同理﹐Tree類別之資料──height變數﹐連外部的Form1_Click()皆可隨意改變它﹔那麼有一天height之內容出問題了﹐將難以追查出錯之緣故﹐這種程式將讓您大傷腦筋﹐因為您已無法掌握狀況了。
  現在的VB程式中﹐能採取較嚴密之保護措施﹐使您較能控制類別內資料的變化狀況。例如﹐

'ex07.bas
'Some Error Here!
Imports System.ComponentModel
Imports System.Drawing
Imports System.WinForms
'-----------------------------------------
Class Tree
  Private varity As String
  Private age As Integer
  Private height As Single
End Class
'-----------------------------------------
Public Class Form1
  Inherits System.WinForms.Form
 
  Public Sub New()
  MyBase.New()
  Form1 = Me
  'This call is required by the Win Form Designer.
  InitializeComponent()
  'TODO: Add any initialization after the InitializeComponent() call
  End Sub
  'Form overrides dispose to clean up the component list.
  Public Overrides Sub Dispose()
  MyBase.Dispose()
  components.Dispose()
  End Sub
#Region " Windows Form Designer generated code "
  .......
#End Region
  Public Sub Form1_Click( ByVal sender As Object, ByVal
  e As System.EventArgs)
  Dim a As New Tree()
  a.height = 2.1
  MessageBox.Show("height = " + str(a.height))
  End Sub
End Class

此程式將原來的Public專用字改為Private﹐對Tree類別之資料成員採取嚴格之保護措施。Public 與Private之區別為──

  Public  表示此類別外之程式可來存取資料成員。
  Private  表示此類別外之程式絕無法直接存取資料成員﹐只有程式成員才能存取資料成員。

所以﹐計算機看到指令── a.height = 2.1,因Tree類別採取嚴格保護措施(private)﹐則Form1_Click()程式不能使用height變數名稱。所以指令── a.height = 2.1錯了。也許您問道﹕這樣豈不是無法存取類別內之資料成員嗎﹖答案是﹕「類別內之程式成員(Member Function) 可存取資料成員﹐而類別外之程式能藉程式成員代之存取資料成員。」
 
  圖1、類別之溝通管道──程式成員

  這如同﹐引信管才能引起炸彈內之化學藥品爆炸﹐人們只能經由引信管引爆之﹐讓人們覺得使用炸彈既又簡單。同樣地﹐物件經由程式成員和外界溝通﹐可減少外界無意中破壞物件內之資料(無意中引爆炸彈)。例如﹕

'ex08.bas
Imports System.ComponentModel
Imports System.Drawing
Imports System.WinForms
'--------------------------------------------------
Class Tree
  Private varity As String
  Private age As Integer
  Private height As Single
  Public Sub input(ByVal hei As Single)
  height = hei
  End Sub
End Class
'--------------------------------------------------
Public Class Form1
  Inherits System.WinForms.Form
 
  Public Sub New()
  MyBase.New()
  Form1 = Me
  'This call is required by the Win Form Designer.
  InitializeComponent()
  'TODO: Add any initialization after the InitializeComponent() call
  End Sub
 
  'Form overrides dispose to clean up the component list.
  Public Overrides Sub Dispose()
  MyBase.Dispose()
  components.Dispose()
  End Sub
#Region " Windows Form Designer generated code "
  .........
#End Region
  Protected Sub Form1_Click( ByVal sender As Object, ByVal
  e As System.EventArgs)
  Dim a As New Tree()
  a.input(2.1)
  MessageBox.Show("OK")
  End Sub
End Class

  將input()擺在Tree類別中﹐為Tree之程式成員﹐它能存取資料成員height之值。把input()程式宣告為Public表示類別外之程式可藉來呼叫它﹐其呼叫格式為──
 
  簡單規則是﹕
  Public 表示授權給外界之程式藉由此格式呼叫程式成員。

如果此程式改寫為﹕

 

'ex09.bas
'Some Error Here!
Imports System.ComponentModel
Imports System.Drawing
Imports System.WinForms
'----------------------------------------------
Class Tree
  Private varity As String
  Private age As Integer
  Private height As Single
  Private Sub input(ByVal hei As Single)
  height = hei
  End Sub
End Class
'-----------------------------------------------
Public Class Form1
  Inherits System.WinForms.Form
 
  Public Sub New()
  MyBase.New()
  Form1 = Me
  'This call is required by the Win Form Designer.
  InitializeComponent()
  'TODO: Add any initialization after the InitializeComponent() call
  End Sub
  'Form overrides dispose to clean up the component list.
  Public Overrides Sub Dispose()
  MyBase.Dispose()
  components.Dispose()
  End Sub
#Region " Windows Form Designer generated code "
  .......
#End Region
  Protected Sub Form1_Click( ByVal sender As Object, ByVal
  e As System.EventArgs)
  Dim a As New Tree()
  a.input(2.1)
  MessageBox("OK")
  End Sub
End Class

這程式有問題﹐因為 input()是Tree類別之Private程式成員而非Public程式成員﹐所以不能使用如下格式──

 
 
所以此程式錯了。  請再看個例子吧﹗

'ex10.bas
Imports System.ComponentModel
Imports System.Drawing
Imports System.WinForms
'-------------------------------------------
Class Tree
  Private varity As String
  Private height As Single
  Public age As Integer
  Public Sub ShowAge()
  MessageBox.Show("Age = " + str(Age))
  End Sub
End Class
'-------------------------------------------
Public Class Form1
  Inherits System.WinForms.Form
 
  Public Sub New()
  MyBase.New()
  Form1 = Me
  'This call is required by the Win Form Designer.
  InitializeComponent()
  'TODO: Add any initialization after the InitializeComponent() call
  End Sub
  'Form overrides dispose to clean up the component list.
  Public Overrides Sub Dispose()
  MyBase.Dispose()
  components.Dispose()
  End Sub
#Region " Windows Form Designer generated code "
  .......
#End Region
  Protected Sub Form1_Click( ByVal sender As Object, ByVal
  e As System.EventArgs)
  Dim a As New Tree()
  a.age = 8
  a.age = a.age + 2
  a.ShowAge()
  End Sub
End Class

Tree類別包含 2個Private成員── variety及height﹐且有 2個Public成員── age及 ShowAge()。由於age是Public資料成員﹐所以Fom1_Click()可使用格式──
 
來存取Tree內之age變數。指令── a.age = 8把8存入物件 a內之age 變數。指令──a.age = a.age + 2使物件a之age變數值加上2﹐成為10。由於ShowAge()程式是Public程式成員﹐也可使用格式──
 
來呼叫 ShowAge()程式。
由於類別(即物件)之目的是保護資料﹐並且提供程式成員來與外界溝通(接受、處理、並反應訊息)。通常﹐資料成員皆宣告為Private﹐而程式成員皆宣告為Public。亦即儘量少用格式──
 
而儘量多用格式──
 
例如﹕

'ex11.bas
Imports System.ComponentModel
Imports System.Drawing
Imports System.WinForms
'--------------------------------------------------------------------
Class Tree
  Private varity As String
  Private age As Integer
  Private height As Single
  Public Sub input(ByVal v As String, ByVal a As Integer, ByVal hei As Single)
  varity = v
  age = a
  height = hei
  End Sub
  Public Sub Show()
  MessageBox.Show(varity + ", " + str(age) + ", " + str(height))
  End Sub
End Class
'---------------------------------------------------------------------
Public Class Form1
  Inherits System.WinForms.Form
 
  Public Sub New()
  MyBase.New()
  Form1 = Me
  'This call is required by the Win Form Designer.
  InitializeComponent()
  'TODO: Add any initialization after the InitializeComponent() call
  End Sub
  'Form overrides dispose to clean up the component list.
  Public Overrides Sub Dispose()
  MyBase.Dispose()
  components.Dispose()
  End Sub
#Region " Windows Form Designer generated code "
  ........
#End Region
  Protected Sub Form1_Click( ByVal sender As Object, ByVal
  e As System.EventArgs)
  Dim a, b As New Tree()
  a.input("peach", 8, 2.1)
  b.input("pinapple", 2, 0.5)
  a.Show()
  b.Show()
  End Sub
End Class

  這個VB程式﹐Tree內之資料成員──variety, age及height皆為Private成員,而input()及Show()程式是Public成員。Form1_Click()程式中﹐首先誕生物件── a及 b。接下來﹐指令──
 
 

把 3項資料分別存入物件 a之資料成員中﹐a 之內容為﹕

 
 
同樣地﹐指令──
  b.input( "pineapple", 2, 0.5 )

也把 3項資料存入物件 b之中﹐則 b之內容為﹕

 
 
最後﹐呼叫Show()程式把物件 a和物件 b之內容顯示出來﹕
 
  peach,  8,  2.1
  pineapple,  2,  .5
n

 


 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-988984/,如需轉載,請註明出處,否則將追究法律責任。

相關文章