VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > VB.net教程 >
  • VB.net学习笔记(八)重载与共享

一、重载

       方法通过形式的变化,达到重载。

       通过重载,创建同名的几个方法,每个方法接收不同的参数或不同类型的参数。

      如下:
 

Public Sub Walk()       '1、重载,无参数



   RaiseEvent Walked(0)



End Sub



Public Sub Walk(ByVal Distance As Integer) '2、重载,带一个参数

    mintTotalDistance += Distance

    RaiseEvent Walked(Distance)

End Sub



Public Sub Walk(Optional ByVal Distance As Integer = 0) '3、上面1和2简化写成一个

    mintTotalDistance += Distance

    RaiseEvent Walked(Distance)

End Sub



       Optional可以合并前两个重载,它的灵活性并不大,只能选择不选或者选择。重载还可以便参数个数不同,或类型不同。

 

       OverLoads 关键字在方法的简单重载中并不需要使用。但,把重载与继承结合时,就需要使用它。

 

二、重载技巧

        为什么.net会根据同名来确定方法的重载呢?

    

      1、方法签名

        .net通过方法签名来确定重载方法分属不同的方法,从而实现运行。因为完全一样的方法编译器会提示出错。

        方法签名:由方法的名称、参数的数据类型来确定。

         Public  Function  Add() As  Integer    ‘方法签名为: f()      f表示方法名,()表示参数

         Public  Function  Add(ByVal  a  As Double) As  Integer  '方法签名为: f(double)     表示参数为double类型

          Public  Function  Add(ByVal  a  Double,byval b as integer ) As  Integer  '方法签名:f(double,integer)

        

          注意:(1)返回值(类型)不是方法签名的一部分。两个方法完全相同,只是返回值类型不一样时,它们的方法签名是一样的。

                                                              这样的不能重载,且编译会出错。

                        (2)参数的名称不重要,只在意它的类型。编译器只看类型,忽略参数的名称。

                        (3)传递方式不重要。编译器不会在意是按值传递还是按引用传递。

 

          2、组合重载与可选。

          重载比可选参数更为灵活。可选参数也有优势,主要在于可提供默认值。

Public Sub DoWork(Byval  x as integer,optional byval y as integer=0 )  '1

     Public Sub DoWork(Byval  x as integer) '2

     Public Sub DoWork(Byval  x as String) '3
  1.  
         上面1和2同时出现会出错,因为1的签名是f(integer),f(integer,integer)  ,2的签名是f(integer).。这样出现了相同的签名,故出错。

 

         上面1和3同时出现不会出错,因为分别是:f(integer),f(integer,integer),f(string)。

          另外:1和3的同时出现,智能提示会提示是3种变体,内部是当作两个方法的重载,这与创建3个不同的重载方法来匹配3个签名是不同的。

二、重载构造函数

       用New可构造(创建)对象(实例),而New后面跟不同的参数,就会形成构造函数的重载。  

      下面是构造函数的重载,所带的参数不同,形成了不同的签名:

  1.  
Public Sub New(Optional ByVal Name As String = "", Optional ByVal BirthDate As Date =#1/1/1900#)

    mstrName = Name

    mdtBirthDate = BirthDate



    Phone("home") = "555-1234"

    Phone("work") = "555-5678"

    sintCounter += 1

    RaiseEvent NewPerson()

End Sub





Public Sub New(ByVal Name As String, ByVal BirthDate As Date)

   mstrName = Name

   mdtBirthDate = BirthDate



   Phone("home") = "555-1234"

   Phone("work") = "555-5678"

   sintCounter += 1

   RaiseEvent NewPerson()

 End Sub

 

二、共享变量、共享方法、共享事件。

       前面都是通过“实例方法”来完成,即必须有一个实例(对象)才能完成工作。

       有时,一此功能无法预测类中实例,也是有实例,也许没有实例,也许无法预知实例(对象)的个数。

       于是产生了一个不依赖对象(实例)的变量、方法、事件。

        这种变量、方法,事件,属于所有对象共享,不属性单独的具体对象,它属于类,被类的所有实例共享。

 

        用Shared来标记,它属性类,而不属于某个对象。比如,一共产生了多少个对象?

        

        1、共享变量

        共享变量只属于类的变量,用Shared标记。类似于C++的Static数据成员 。

        如下:每构造(创建)一个对象(实例)时,就会自动增加sintCounter的计数。

 


Public Class Person

    '.......其它代码

    Private Shared sintCounter As Integer   '共享变量



    Public Sub New(ByVal Name As String, ByVal BirthDate As Date)

        mstrName = Name

        mdtBirthDate = BirthDate



        Phone("home") = "555-1234"

        Phone("work") = "555-5678"

        sintCounter += 1          ’每增加一个对象自动计数

        RaiseEvent NewPerson()

    End Sub



    Public Sub New()

        Phone("home") = "555-1234"

        Phone("work") = "555-5678"

        sintCounter += 1          '自动统计计数

        RaiseEvent NewPerson()

    End Sub



    '......

End Class

 

          2、共享方法

          同理,共享方法也属于类,不属于任何对象,不能访问任何对象中的任何实例变量。

           如果想访问其它实例,只能通过传参数的方法间接取得。否则将出错。

                 简单地说:  普遍性不能访问个例,个例可以访问普通性。

 

          共享方法属于类,当然可以访问类中其它的共享变量和方法,因为他们级别相同。

 

          共享方法,同样是在前加上Shared关键字即可。

 

          这其实和C++的概念相同,复习一下:

共享数据(变量)与共享方法分别对应C++的静态数据成员和静态成员函数。 同样共享方法属性类,它在内存同普通方法一样,只有一个副本。 C++中

1、静态成员函数为什么没有this指针? this指的是当前对象,而静态成员函数是属于类的,要用类来访问

2、静态成员函数为什么只能访问静态成员? 静态成员函数不接受隐含的this自变量。普通成员是根据this指针定位函数位置, 因此无法确定普通成员的位置,它就无法访问自己类的非静态成员。    当然可以变向访问一些东西,比如声明成员函数全为静态,就可访问。    另外,在静态成员函数中接收对象参数,通过对象参数来访问对应的普通成员。

3、为什么虚函数必须是非静态成员函数? 因为虚函数是动态绑定的,也就是在派生类中可以被覆盖的。而静态成员函数的定义 本身就是静态绑定的,这两者相互矛盾,所以不能是静态成员函数。

 

 

 

        3、共享属性

        共享属性,本质上也是共享方法,它们规律相同。

         

        故也是在其中加上Shared即可表明是共享属性。


Public Shared ReadOnly Property PersonCount() As Integer

    Get

        Return sintCounter

    End Get

End Property
  1.  
           无论是共享变量、共享方法、共享属性,它们都是通过类名进行访问:

 


    Dim myPerson As Person

    myPerson = New Person

    myPerson = New Person

    myPerson = New Person

    MessageBox.Show(Person.PersonCount()) '1、标准写法,共享数据通过类名访问

    MessageBox.Show(PersonCount())        '2、错误,未限定范围(不知是哪个类的)

    MessageBox.Show(myPerson.PersonCount()) '3、非标准(发出警告)因模糊了实例与类的共享成员(不推荐)

          下面是共享属性访问共享变量:(这个共享变量翻译成共享数据估计更好理解)

 


Public Shared ReadOnly Property PersonCount() As Integer    '只读属性PersonCount

    Get

        Return sintCounter

    End Get

End Property
  1.  
          下面是共享方法,通过传递参数的方法,访问具体的实例:
Public Shared Function CompareAge(ByVal Person1 As Person, ByVal Person2 As Person) As Boolean

    Return Person1.Age > Person2.Age

End Function
      共享属性的另一例:
Public Shared ReadOnly Property RetirementAge() As Integer   '只读属性RetirementAge

    Get

        Return 62

    End Get

End Property

          4、共享事件

           共享事件的声明定义:          

 

    Public Shared Event NewPerson()

          共享事件可以在实例方法或共享方法中引发。

          普通事件只能在普通方法中引发,而普通事件不能在共享方法中引发(因为共享方法中无法确定针对的是哪一个普通的事件)。

          如图:大方框表示方法,小方框表示插入其内的引发事件(RaiseEvent)

          下面是普通方法引发共享事件:

Public Class Person

  '.........

  Public Shared Event NewPerson()



  Public Sub New(ByVal Name As String, ByVal BirthDate As Date)

    mstrName = Name

    mdtBirthDate = BirthDate



    Phone("home") = "555-1234"

    Phone("work") = "555-5678"

    sintCounter += 1

    RaiseEvent NewPerson()   '普通方法调用共享事件

  End Sub



  Public Sub New()

    Phone("home") = "555-1234"

    Phone("work") = "555-5678"

    sintCounter += 1

    RaiseEvent NewPerson()

  End Sub

  '..........

End Class
              复习:事件其实就类似于回调函数。

                           一般调用方法后,就不再进行,而回调函数,是在调用方法后,该方法再次调用另一个函数(事件)。

               如图:

               构造中有引发事件,通过AddHandler把构造中的事件与客户中的另一个方法联系起来。于是调用构造时就会引出客户中的方法。

 

 

       

            5、共享构造函数。

            构造函数本身就是在创建实例之前。

            而共享构造函数更是在构造函数之前,在它的生命中,只被调用一次,且在第一次使用该类(不是实例)之前调用。

         

           共享构造函数不能直接调用,因此不能接收任何参数,它只能与类的共享变量或者其它共享方法进行交互(访问)。

 

         通常,它用于初始化对象内部的共享字段。比如计算类的对象的个数,想把初始计数设置为0 

Private Shared sintCounter As Integer

  Shared Sub New()

      sintCounter = 0

  End Sub
三、运算符重载。

        对象的+,-,X,等运算并没有定义,怎么办,可利用现有的运算符,通过重载的方法,实例类似基本类型的运算方式。

 

        运算符重载,用Operator来指明,且必须用Shared进行限定。(类似于C++的友元重载)

         

       而且VB.net的运算符重载很怪,很多运算符必须成对出现重载,否则出错。

       比如:=和<>,>和<等必须成对出现重载:

 


  1. Public Class Form1
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    
            Dim a As Person = New Person(3)
    
            Dim b As Person = New Person(4)
    
            a = a + 3
    
            TextBox1.Text = a.show()
    
        End Sub
    
    End Class
    
    
    
    
    
    Public Class Person
    
        Private b As Int32
    
        Public Sub New(Optional d As Int32 = 0)
    
            b = d
    
        End Sub
    
        Public Shared Operator +(ByVal f As Person, ByVal d As Int32) As Person
    
            f.b = f.b + d
    
            Return f
    
        End Operator
    
        Public Shared Operator =(ByVal c As Person, ByVal d As Person) As Boolean
    
            Return c.b = d.b
    
        End Operator
    
        'Public Shared Operator >(ByVal c As Person, ByVal d As Person) As Boolean
    
        '    Return c.b > d.b
    
        'End Operator
    
        'Public Shared Operator <(ByVal c As Person, ByVal d As Person) As Boolean
    
        '    Return c.b < d.b
    
        'End Operator
    
        Public Shared Operator <>(ByVal c As Person, ByVal d As Person) As Boolean
    
            Return c.b <> d.b
    
        End Operator
    
        Public Function show() As Int32
    
            Return b
    
        End Function
    
    End Class
              另外,对于CType运算符的重载,还必须出现Narrowing或者Widening,用来指明取值范围是扩大还是收缩。
    
    
    
        Public Shared Narrowing Operator CType(ByVal name As String) As Person
    
            Dim obj As New Person   'Ctype必须带有Narrowing(收缩)或Widening(扩展)来指明类型的变化范围
    
            obj.Name = name
    
            Return obj
    
        End Operator
    
        Public Shared Widening Operator CType(ByVal obj As Person) As String
    
        Return obj.Name 'Person->String转换,由窄转向宽,扩展,故用windening
    
        End Operator

 

 

           运算符重载的说明:

         1、= 和<>      等于与不等于,二元运算,必须成对出现。

          2、>和<        大于和小于,   二元运算,必须成对出现重载。

          3、>=和<=     大于等于和小于等于,二元,必须成对出现。

          4、IsFalse和IsTrue     布尔转换,只能出现在重载中,用于支持AndAlso,OrElse。接收一个对象。必须成对出现。

          5、CType           类型转换,接收一个参数(返回值是另一转换类型),必须与Narrowing或Widening结合。

          6、+和-                加与减,一元或二元。(一元:a+=b,二元:a+b)

          7、*,/,\,^,Mod             乘、除、指数、整除、取余,二元运算。

          8、&                       连接,二元(a&b)

          9、<<和>>          位移。二元(a>>b),第二个参数必须是integer类型(指定位移数目)

          10、And,Or, Xor         逻辑比较(或位操作),二元(返回值是布尔是逻辑,返回值是其它数据类型是按位)

          11、Like                    模式比较。二元(a  Like b)

 

 

          AndAlso与OrElse

         这比原And和Or更进步了,它们实现最短路径实现法,只要第一个能确定结果则不再进行第二比较,只有第一个不能确定全部结果时

         才进行第二步,因为实现方式较为最短。

 

          AndAlso与OrElse的重载。

         百度N久没看到实例。查了MSDN,翻书几本没找到实例。

         试着写了一个简单的重载它们的例子:

 


Public Class Form1

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

        Dim a As Person = New Person(3)

        Dim b As Person = New Person(4)

        a = a + 3

        TextBox1.Text = a.show()

    End Sub

End Class





Public Class Person

    Private b As Int32

    Public Sub New(Optional d As Int32 = 0)

        b = d

    End Sub

    Public Shared Operator +(ByVal f As Person, ByVal d As Int32) As Person

        f.b = f.b + d

        Return f

    End Operator

    Public Shared Operator =(ByVal c As Person, ByVal d As Person) As Boolean

        Return c.b = d.b

    End Operator

    'Public Shared Operator >(ByVal c As Person, ByVal d As Person) As Boolean

    '    Return c.b > d.b

    'End Operator

    'Public Shared Operator <(ByVal c As Person, ByVal d As Person) As Boolean

    '    Return c.b < d.b

    'End Operator

    Public Shared Operator <>(ByVal c As Person, ByVal d As Person) As Boolean

        Return c.b <> d.b

    End Operator

    Public Function show() As Int32

        Return b

    End Function

End Class
          另外,对于CType运算符的重载,还必须出现Narrowing或者Widening,用来指明取值范围是扩大还是收缩。



    Public Shared Narrowing Operator CType(ByVal name As String) As Person

        Dim obj As New Person   'Ctype必须带有Narrowing(收缩)或Widening(扩展)来指明类型的变化范围

        obj.Name = name

        Return obj

    End Operator

    Public Shared Widening Operator CType(ByVal obj As Person) As String

    Return obj.Name 'Person->String转换,由窄转向宽,扩展,故用windening

    End Operator

        可以看到,这两个重载不能直接重载,只能间接通过IsFalse,IsTrue及And和Or的重载来实现。

       重载实现的方法是:

      1、AndAlso重载:   (1)重载And(接收两个自定义类型的对象参数),并返回一个自定义类型的对象作为结果。

                                                       注意这里返回不是Boolean,因为这个返回值为下面二步作准备。

                                            (2)重载IsFalse,使用自定义类型的对象参数,返回值为Boolean

       2、OrElse重载:(1)重载Or(接收两个自定义类型的对象参数),并返回一个自定义类型的对象作为结果。

                                                       注意这里返回不是Boolean,因为这个返回值为下面二步作准备。

                                            (2)重载IsTrue,使用自定义类型的对象参数,返回值为Boolean

 

 

为什么要这样定义重载呢?看一下andalso,orelse的定义: