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和2同时出现会出错,因为1的签名是f(integer),f(integer,integer),2的签名是f(integer).。这样出现了相同的签名,故出错。

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

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





二、重载构造函数

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

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

    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

无论是共享变量、共享方法、共享属性,它们都是通过类名进行访问:
        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
下面是共享方法,通过传递参数的方法,访问具体的实例:
    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的运算符重载很怪,很多运算符必须成对出现重载,否则出错。

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

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 obj1 As Person = New Person(0)
        Dim obj2 As Person = New Person(1)
        If obj1 AndAlso obj2 Then
            TextBox1.Text = True
        Else
            TextBox1.Text = False
        End If
    End Sub
End Class
Public Class Person
    Private intAge As Int32
    Public Property Age() As Int32
        Get
            Return intAge
        End Get
        Set(value As Int32)
            intAge = value
        End Set
    End Property
    Public Sub New(Optional a As Int32 = 0)
        intAge = a
    End Sub
    Public Shared Operator And(ByVal a As Person,ByVal b As Person) As Person '重载And注意返回对象(不是boolean)
        If a.intAge And b.intAge Then                                          '这样就为下面短路判断isFalse做好准备
            Return New Person(1)
        Else
            Return New Person(0)
        End If
    End Operator
    Public Shared Operator IsFalse(ByVal a As Person) As Boolean      '重载IsFalse(必须配套重载IsTrue)
        Dim b As Boolean = Not CType(a.intAge,Boolean)
        Return b
    End Operator
    Public Shared Operator IsTrue(ByVal a As Person) As Boolean
        Dim b As Boolean = CType(a.intAge,Boolean)
        Return b
    End Operator
End Class

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

重载实现的方法是:

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

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

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

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

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

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


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

Public Function AndAlso(x as Boolean,y as Boolean) As Boolean 
    Return IIf(x,x And y,False) 
End Function 
  
Public Function OrElse(x as Boolean,True,x Or y) 
End Function

通过And或Or先判断一下(IsTrue或IsFalse),来确定AndAlse或OrElse。


另外:

不能在代码中显式调用IsFalse,但 Visual Basic 编译器可以用它从AndAlso子句生成代码如果您定义一个类或结构,然后在AndAlso子句中使用这种类型的变量,则必须在该类或结构上定义IsFalse

编译器将IsFalseIsTrue运算符当作匹配对。这意味着如果您定义其中一个运算符,则还必须定义另外一个。

猜你在找的VB相关文章