首页 > 编程 > .NET > 正文

VB.Net中文教程(7) Me参考值

2024-07-10 13:01:17
字体:
来源:转载
供稿:网友
  • 网站运营seo文章大全
  • 提供全面的站长运营经验及seo技术!
  • 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()﹐这是对的。n

    发表评论 共有条评论
    用户名: 密码:
    验证码: 匿名发表