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++的静态数据成员和静态成员函数。
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。 编译器将IsFalse和IsTrue运算符当作匹配对。这意味着如果您定义其中一个运算符,则还必须定义另外一个。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- 吴恩达机器学习 - 逻辑回归的正则化
- 如何在C#中使指针通用?
- 在Oracle 10gR2中为单条sql运行SQL Access Advisor
- objective-c – 使用__attribute __((nonnull(2)))声明方法
- c# – 任何ASP.net应用程序(或大多数)可以使用Mono在Linux下
- c# – 记录文件名,日志中的行号.我需要传递StackFrame吗?
- ruby-on-rails – 使用Formtastic和ActiveAdmin输入图像文件
- Swift:有人可以为我解释这个语法`numbers.sort {$0> $1}`吗
- NoSQL数据库之Redis数据库管理(PHP-REDIS实例)
- 《Spring源码深度解析》阅读笔记4-容器的基本实现之获取XML