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运算符当作匹配对。这意味着如果您定义其中一个运算符,则还必须定义另外一个。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Format[$] ( expr [ , fmt ] ) format 返回变体型 format$ 强制返回为文本 -------------------------------- 数字类型的格式化 --------------------------------     固定格式参数:     General Number 普通数字,如可以用来去掉千位分隔号     format$("100,1
VB6或者ASP 格式化时间为 MM/dd/yyyy 格式,竟然没有好的办法, Format 或者FormatDateTime 竟然结果和系统设置的区域语言的日期和时间格式相关。意思是尽管你用诸如 Format(Now, "MM/dd/yyyy"),如果系统的设置格式区域语言的日期和时间格式分隔符是"-",那他还会显示为 MM-dd-yyyy     只有拼凑: <%response.write
在项目中添加如下代码:新建窗口来显示异常信息。 Namespace My ‘全局错误处理,新的解决方案直接添加本ApplicationEvents.vb 到工程即可 ‘添加后还需要一个From用来显示错误。如果到这步还不会则需要先打好基础啦 ‘======================================================== ‘以下事件
转了这一篇文章,原来一直想用C#做k3的插件开发,vb没有C#用的爽呀,这篇文章写与2011年,看来我以前没有认真去找这个方法呀。 https://blog.csdn.net/chzjxgd/article/details/6176325 金蝶K3 BOS的插件官方是用VB6编写的,如果  能用.Net下的语言工具开发BOS插件是一件很愉快的事情,其中缘由不言而喻,而本文则是个人首创,实现在了用V
Sub 分列() ‘以空格为分隔符,连续空格只算1个。对所选中的单元格进行处理 Dim m As Range, tmpStr As String, s As String Dim x As Integer, y As Integer, subStr As String If MsgBox("确定要分列处理吗?请确定分列的数据会覆盖它后面的单元格!", _
  窗体代码 1 Private Sub Text1_OLEDragDrop(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single) 2 Dim path As String, hash As String 3 For Each fil
  Imports MySql.Data.MySqlClient Public Class Form1 ‘ GLOBAL DECLARATIONS Dim conString As String = "Server=localhost;Database=net2;Uid=root;Pwd=123456;" Dim con As New MySqlConnection
‘導入命名空間 Imports ADODB Imports Microsoft.Office.Interop   Private Sub A1() Dim Sql As String Dim Cnn As New ADODB.Connection Dim Rs As New ADODB.Recordset Dim S As String   S = "Provider=OraOLEDB.Oracl
Imports System.IO Imports System.Threading Imports System.Diagnostics Public Class Form1 Dim A(254) As String    Function ping(ByVal IP As Integer) As String Dim IPAddress As String IPAddress = "10.0.
VB运行EXE程序,并等待其运行结束 参考:https://blog.csdn.net/useway/article/details/5494084 Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long Pr
今天碰到一个问题,登陆的时候,如果不需要验证手机号为空,则不去验证手机号 因为登陆的时候所有的验证信息都存放在一个数组里 Dim CheckUserInfo() As String ={UserBirthday, SecEmail, UserMob, UserSex, RealNameFirst, RealName, CheckCardID, CheckCardType, Contactemail
在VB6.0中,数据访问接口有三种: 1、ActiveX数据对象(ADO) 2、远程数据对象(RDO) 3、数据访问对象(DAO) 1.使用ADO(ActiveX Data Objec,ActiveX数据对象)连接SQL Server 1)使用ADO控件连接 使用ADO控件的ConnectionString属性就可以连接SQL Server,该属性包含一个由分号分隔的argument=value语
注:大家如果没有VB6.0的安装文件,可自行百度一下下载,一般文件大小在200M左右的均为完整版的软件,可以使用。   特别提示:安装此软件的时候最好退出360杀毒软件(包括360安全卫士,电脑管家等,如果电脑上有这些软件的话),因为现如今的360杀毒软件直接会对VB6.0软件误报,这样的话就可能会在安装过程中被误报阻止而导致安装失败,或者是安装后缺乏很多必须的组件(其它的杀毒软件或安全卫士之类的
Private Sub Form_Load() Call conndb End Sub Private Function conndb() Dim cn As New ADODB.Connection Dim rs As New ADODB.Recordset Dim strCn, sql As String Dim db_host As String Dim db_user As String
  PPSM06S70:  Add  moddate  EDITSPRINTJOB:  MAX(TO_CHAR(ETRN.MODDATE, ‘yyyy/mm/dd/HH24:MI AM‘)) ACTUAL_SHIPDATE   4.Test Scenario (1) :Query SQL Test DN:8016578337 SELECT CTRN.TKCTID TRUCK_ID,        
  沒有出現CrystalReportViewer時,須安裝CRforVS_13_0. 新增1個數據集,新增1個數據表,添加二列,列名要和資料庫名一樣. 修改目標Framework 修改app.config, <startup >改成<startup useLegacyV2RuntimeActivationPolicy ="true">  CrystalReport1.rpt增加數據庫專家 在表單
Imports System.Threading Imports System Public Class Form1 Dim th1, th2 As Thread Public Sub Method1() Dim i As Integer For i = 1 To 100 If Me.Label1.BackColor =
Friend Const PROCESS_ALL_ACCESS = &H1F0FFF = 2035711 Friend Const PROCESS_VM_READ = &H10 Friend Const PROCESS_VM_WRITE = &H20 Friend Const PAGE_READONLY = &H2 Friend Const PAGE_READWRITE = &H4 Friend
以下代码随手写的 并没有大量测试 效率也有待提升 如果需要C#的请自行转换 Function SplitBytes(Data As Byte(), Delimiter As Byte()) As List(Of Byte()) Dim i = 0 Dim List As New List(Of Byte()) Dim bytes As New
Imports System.Data.SqlClient Public Class Form1 REM Public conn1 As SqlConnection = New SqlConnection("server=.; Integrated Security=False;Initial Catalog= mydatabase1; User ID= sa;password")