Me關鍵字在.NET中的使用 www.yescnet.com CNET中文網
ME 函數大家都很熟了,在VB6中ME只能應用于窗體,但在.NET中就沒用這個限制了,快來看看使用方法吧!!!!!!!!
?????? 內容 ?????? v 1. 活用Me參考值 1.1認識Me參考值 1.2程序傳回Me參考值
v 2. 認深入了解Me參考值
1. 使用Me參考值 1.1 認識Me參考值
類別之程序成員(Procedure Member) 各含一個Me參考變量﹐它永遠參考到「目前對象」(Current Object)。目前對象就是正接受并處理訊息之對象。例如﹐
'ex01.bas Imports System.ComponentModel Imports System.Drawing Imports System.WinForms '------------------------------------------------------------------------------ Public Class Fee Private amount As Decimal
Public Sub New(ByVal amt As Decimal) Me.amount = amt End Sub Public Sub disp() MessageBox.Show("Amount is " + str( Me.amount )) 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 Fee(100) Dim b As New Fee(80) a.disp() b.disp() End Sub End Class
此程序輸出如下﹕Amount is 100 Amount is 80
a 和 b是Fee類別之對象。當計算機執行指令── a.disp()
a 就是目前對象﹐disp()程序里的Me正參考到對象a。
也可看成:
圖1、 Me參考值與目前對象
請注意﹕Me參考到對象a﹐也就是Me與a皆參考到同一個對象。 當計算機執行另一指令── b.disp()時,b 即為目前對象﹐而disp()程序之Me參考正指向對象 b。
由于Me正參考到對象b﹐所以Me與b參考到同一個對象。寫程序時﹐宜充分利用Me參考。
1.2 程序傳回Me參考值
在應用上﹐程序常傳回Me參考值﹐可創造奇妙的效果﹐這種效果也是VB的重要特色。希望您能仔細了解Me指針之使用場合﹐能讓您寫出完美的OOP程序來﹗現在﹐請看個熟悉的程序──
'ex02.bas Imports System.ComponentModel Imports System.Drawing Imports System.WinForms '------------------------------------------------------------------------------ Public Class Money Private balance As Decimal Public Sub New(ByVal amount As Decimal) balance = amount End Sub Public Sub add(ByVal saving As Decimal) balance = balance + saving End Sub Public Sub Display() MessageBox.Show("Balance is " + str(balance)) 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 orange As New Money(100) orange.add(300) orange.add(80) orange.Display() End Sub End Class
此程序輸出如下﹕Balance is 480
Money 類別的 balance資料﹐記錄存款余額。main()內之對象orange接受兩訊息──add(300)及add(80) ﹐欲存入兩項金額。
指令── orange.add(300) orange.add(80)
表示﹕先存入 300元再存入80元﹐有先后次序。若上述圖形改為──
則更具次序感。于是﹐上述指令相當于──
這種效果﹐不太陌生吧﹗回憶小學時,班長喊著:「起立、敬禮、坐下」,您不是連續接受到三個訊息嗎?漸漸地﹐您已能設計出像日常生活這般親切之對象了。不過﹐俗語說﹕「萬丈高樓平地起」﹐還是必須先對Me參考有充分了解才行﹗請看個程序──
'ex03.bas Imports System.ComponentModel Imports System.Drawing Imports System.WinForms '----------------------------------------------------------------------------------- Public Class Money Private balance As Decimal Public Sub New(ByVal amount As Decimal) balance = amount End Sub Public Function add(ByVal saving As Decimal) As Money balance = balance + saving add = Me End Function Public Sub Display() MessageBox.Show("Balance is " + str(balance)) 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 orange As New Money(100) orange.add(300).add(80) orange.Display() End Sub End Class
此程序輸出如下﹕Balance is 480 由于Me永遠參考到目前對象﹐此刻Me正參考到對象orange。
圖2、 程序傳回目前對象之參考值
oragne對象就是Me所指之對象﹐也可以說Me與orange皆參考到同一個對象。指令── add = Me
傳回目前對象之參考值──即orange對象之參考。add() 程序之定義──
于是add()把目前對象之參考值Me傳回Form1_Click()。此刻﹐orange.add(300)之值也是參考值,與orange參考到同一個對象。
于是,Form1_Click()程序之指令──
成為orange對象之別名了。 原來的指令── orange.add(300).add(80) 相當于── orange.add(80)
不過﹐此時orange對象之 balance變量值為400元﹐而非原來的100元了。此orange再接受訊息── add(80)﹐其 balance值增加為480 元。orange接到第 2個訊息── add(80)時﹐計算機再執行add() 程序﹐其再度傳回orange的參考值﹐使得整個指令──
又成為orange之別名。因之﹐亦能把disp()訊息接于其后﹐如下﹕
'ex04.bas Imports System.ComponentModel Imports System.Drawing Imports System.WinForms '------------------------------------------------------------------------------------ Public Class Money Private balance As Decimal Public Sub New(ByVal amount As Decimal) balance = amount End Sub Public Function add(ByVal saving As Decimal) As Money balance = balance + saving add = Me End Function Public Sub Display() MessageBox.Show("Balance is " + str(balance)) 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 orange As New Money(100) orange.add(300).add(80).Display() End Sub End Class
此程序輸出如下﹕Balance is 480 orange對象接到第 1個訊息──add(300)﹐計算機就執行add()程序,執行到結尾指令﹐傳回Me(即orange對象)參考值。此時Form1_Click()的orange.add(300)就是orange對象之參考值﹐亦即orange.add() 是orange對象之別名﹔則orange和 orange.add(300)重合在一起﹐代表著同一對象──原來的orange對象。
接下來﹐第 2個訊息──add(80)傳給orange.add(300) ﹐相當于傳給orange對象。再度執行到 add()里的的add = Me指令時﹐又令orange.add(300).add(80) 成為 orange.add(300)之別名﹐即orange之別名﹔于是﹐三者代表同一對象──原來的orange對象。
接下來﹐第3個訊息──Display傳給orange.add(300).add(80) ﹐相當于傳給orange對象。
于是輸出orange對象內的balance值。 以程序傳回Me參考值之技巧將應用于許多方面。為了更了解這種方法﹐請看個特殊情形── 程序傳回新對象之參考值。此對象不是目前對象,但內容是從目前對象拷貝而來。這不同于傳回Me參考值的情形﹐兩種用法常令人搞混﹗現在﹐把程序改為──
'ex05.bas Imports System.ComponentModel Imports System.Drawing Imports System.WinForms '------------------------------------------------------------------------------------ Public Class Money Private balance As Decimal Public Sub New(ByVal amount As Decimal) balance = amount End Sub Public Function add(ByVal saving As Decimal) As Money Dim newobj As Money newobj = New Money( balance + saving ) add = newobj End Function Public Sub Display() MessageBox.Show("Balance is " + str(balance)) 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 orange As New Money(100) orange.add(300).add(80).Display() End Sub End Class
此程序輸出如下﹕Balance is 480
當orange對象接到第 1個訊息──add(300)﹐計算機就執行add()程序﹐誕生一個Money類別的新對象﹐把目前對象內容(即orange對象之值)拷貝一份給Form1_Click()。這份拷貝就是orange.add(300)之值。
orange.add(300) 即為拷貝回來的那份對象﹐并非原來的orange對象。當訊息──add(80)傳給orange.add(300)所代表的對象時﹐計算機就執行add()函數﹐此時目前對象是orange.add(300) 而非原來的orange。執行時﹐又把目前對象──orange.add(300)內容拷貝一份給新誕生的對象,傳回給Form1_Click()程序﹐這份拷貝就是orange.add(300).add(80) 之值。
由于每回執行add()就產生一份新對象(雖然內容相同﹐但占不同的內存空間)﹐其后的訊息皆傳給add()所誕生之新對象﹐而非orange對象,所以這些訊息皆不影響原來orange對象之內容。 請注意﹕Display()并未傳回對象之參考值﹐則Display()訊息之后不得再接其它訊息了。所以﹐如果Form1_Click()程序改寫如下,那就錯了──
Protected Sub Form1_Click( ByVal sender As Object, ByVal e As System.EventArgs) Dim orange As New Money(100) orange.add(300).Display().add(80) 'Error! End Sub End Class
因Display()不傳回對象之參考值﹐則指令──
其后之訊息──add(80) 是錯的。如何改正呢﹖很簡單﹐只需叫Display()程序傳回 Me(目前對象之參考值)或新對象之參考值即可﹐如下﹕
'ex06.bas Imports System.ComponentModel Imports System.Drawing Imports System.WinForms '------------------------------------------------------------------------------------- Public Class Money Private balance As Decimal Public Sub New(ByVal amount As Decimal) balance = amount End Sub Public Function add(ByVal saving As Decimal) As Money Dim newobj As Money newobj = New Money( balance + saving ) add = newobj End Function Public Function Display() As Money MessageBox.Show("Balance is " + str(balance)) Display = Me 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 orange As New Money(100) orange.Display().add(300).Display().add(80).Display() End Sub End Class
此程序輸出﹕ Balance is 100 Balance is 400 Balance is 480
此程序中﹐orange先接受Display()訊息﹐印出存款額﹔再接受add(300)訊息﹐使存款額提高 300元﹐再接受Display()訊息﹐依序下去。Display()傳回來目前對象orange之參考值,add()則傳回新誕生對象之參考值。
2. 深入了解Me參考
VB在編譯時﹐會自動為程序成員產生Me參考變量﹐并令Me固定參考到目前對象(Current Object)。于此將細談VB如何產生Me參考變量﹐讓您更能深刻了解Me參考變量的特性和角色。首先﹐VB在編譯程序成員時﹐會暗中偷加上1 個參考參數──Me﹐成為該程序成員的第1 個參數。例如﹕
Class Person Private name As String Priavte age As Integer Public Sun New(ByVal na As String, ByVal a As Integer) name = na age = a End Sub Public Sub Display() Messagebox.Show( name + ", " + str( age ) ) End Sub End Class
在編譯此程序時﹐VB會將偷加上Me參考變量如下﹕
Class Person Private name As String Priavte age As Integer Public Sun New( ByVal Me As Person, ByVal na As String, ByVal a As Integer) Me.name = na Me.age = a End Sub Public Sub Display(ByVal Me As Person) Messagebox.Show( Me.name + ", " + str( Me.age ) ) End Sub End Class
無論是在New()或Display()程序里﹐Me皆固定參考到目前對象﹐您不能改變Me之值。接下來﹐請看如何令Me參考到目前對象﹖假如有個Form1_Click()程序如下﹕
Sub Form1_Click( .... ) Dim x As New Person("Tom", 26) x.Display() End Sub
VB在編譯時﹐會把指令──x.Display()轉換為﹕ Person_Display(x)
意謂著﹕呼叫Person類別的Display()程序來處理x 對象之內容。在呼叫這程序時﹐就把x參考值傳遞給Display()程序里的Me參數﹐如下﹕
于是﹐Me就固定指向x對象了﹐而這x 對象就是我們欲處理之對象﹐亦 即就是目前對象了。請再看個例子吧﹗若Person類別改為﹕
Class Person Private name As String Priavte age As Integer Public Sun New(ByVal na As String, ByVal a As Integer) name = na age = a End Sub Public Sub Print() Me.Display() End Sub Public Sub Display() Messagebox.Show( name + ", " + str( age ) ) End Sub End Class
則VB會為這3 個程序成員加上Me參考值。其中Print()程序轉換如下﹕
Public Sub Print(ByVal Me As Person) Person_Display( Me ) End Sub
上述的Me.Display()轉換為Person_Display( Me )之后﹐就把這Print()內的Me值傳給了Display()內的Me了﹐此時兩個程序內的Me皆參考到目前對象了。 以上所提的一般程序成員并不包括共享程序成員(Shared Member Function)。還記得嗎﹖共享程序成員的目的是﹕處理有關整個類別的事情﹐而不是用來處理對象之內容。在另一方面﹐Me參考到目前對象﹐一般程序成員經由Me來存取目前對象之內容。既然共享程序成員不需存取某特定對象之值﹐當然就不需要Me參考變量了﹐因之VB并不會為共享程序成員偷加上Me參考變量。簡而言之﹐VB的規則是──
「VB編譯時﹐并不會為共享程序成員加上Me參考變量﹐所以 共享程序成員里沒有Me參考變量﹐也就無法存取對象之內容」
如前面所述﹐在呼叫一般程序成員時﹐必須把目前對象之參考值傳遞過去給該程序成員。但共享程序成員里并無Me參考﹐所以無法呼叫一般程序成員。可得知VB的規則── 「共享程序成員不能呼叫一般程序成員﹐但可呼叫別的共享程序成員」
反之﹐一般程序成員卻可呼叫共享程序成員。例如﹕
Class Person Private name As String Priavte age As Integer Shared plast As Person
Public Sun New(ByVal na As String, ByVal a As Integer) name = na age = a plast = Me End Sub Shared Sub DispLast() plast.Display() 'Display() Error !! End Sub Public Sub Print() DispLast() End Sub Public Sub Display() Messagebox.Show( name + ", " + str( age ) ) End Sub End Class
Display()是一般程序成員﹐共享程序成員DispLast()不能直接呼叫Display()程序如下﹕ Shared Sub DispLast() Display() Error !! End Sub
因為VB會將之轉換為──
Shared Sub DispLast() Person_Display( Me ) Error !! End Sub
但DispLast()是共享程序成員﹐并無Me參考變量﹐所以錯了。至于Print() 呼叫DispLast()﹐VB將之轉換為──
Public Sub Print( ByVal Me As Person ) Person_DispLast() End Sub
雖然Print() 內有Me參考﹐但DispLast()是靜態程序成員并不需要Me ﹐Print() 并未把Me傳給DispLast()﹐這是對的
|