教程 类和对象
Posted VB.Net
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了教程 类和对象相关的知识,希望对你有一定的参考价值。
版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。
本文是《Visual Basic.Net 循序渐进》教程的一部分,详细目录请参看:
《Visual Basic.Net 循序渐进》详细目录
第6章 类和对象
俗语“物以类聚”,古人很早就对具有相同特征的事物进行了分门别类。
类是一个抽象的概念,它描述了一系列具有相同概念特征的对象,同时为这些对象定义了字段、属性、过程和事件等。例如猫科动物是一个类,它继承于哺乳动物(实际哺乳动物到猫科动物之间还相隔了几个类,这里做了简化),猫科动物具有哺乳动物的所有特征,同时也有自己独有的一些特征;同样,狸花猫也是一个类,它继承于猫科动物,也有与其它猫科动物不同的特征。
对象是类的具体实例,在VB.Net中,每个对象都由类定义。创建类后,就可以创建属于该类的任意对象。例如定义一只具体的狸花猫,就是狸花猫类的实例。
“猫捉老鼠”,这里的猫是抽象的,指的是猫这个类;而如果说“某某人家里的猫昨天捉到一只老鼠”,这里的猫是具体的(某一只)猫,是真实存在的,这就是具体的对象。
类和对象是面向对象编程中一个重要的概念,事实上,在前面的章节中已经用到了类的概念。
由于类和对象所涉及的内容很广,本书为了简化,在本章中主要讲解最常用的内容。
6.1 建立类
当创建项目后,可以通过以下方法来添加类文件:
1、点击菜单【项目】|【添加类】;
2、点击菜单【项目】|【添加新项】;
3、右击【解决方案资源管理器】中的项目名称,从弹出菜单中点击【添加】|【新建项】或者【添加】|【类】。
上面方法任选其一,然后从【添加新项】窗口中选中“类”,点击“添加”按钮,如下图所示:
图6-1 添加类文件
新添加的类对应文件默认名称为:Class1.vb。
6.2 类的定义
当添加类完成后,VB.Net编辑器将默认建立与类文件同名的类,如6.2节中建立的类为Class1:
Public Class Class1
End Class
类的定义是以Class开始和End Class结尾的代码。例如以下代码定义了一个Cat类:
Public Class Cat
……(具体代码)
End Class
通常而言,可以在一个.vb文件中包含多个类。但建议不同的类使用不同的文件保存。
同一个类,也可以分为不同的文件保存,但是必须在前面加上Partial关键词,例如下面的代码建立了Cat类,并将该类的属性和字段分别放到两个文件中:
‘Class1.vb
Partial Public Class Cat
Public Property catweight As Single
End Class
‘Class2.vb
Partial Public Class Cat
Public catname As String
End Class
6.3 类成员
类成员包括类的字段、属性、方法等。通常情况下类成员的作用域通过Public、Private、Protected、Friend来声明。在第2.9节已经学习了作用域的基础,这里结合类讲解类中成员的作用域:
Public:在类以外的代码中可以调用Public标明的成员。
Private:在类以外的代码中不能调用Private标明的成员。
Protected:通常在派生类中使用。父类中被标识Public的成员将被暴露给所有其它的代码,而子类又不能使用父类中Private标识的成员,这时就可以使用Protected,既防止别的代码调用该成员,又能让子类使用该成员。
Friend:可以使某个成员相对当前程序集可见。
6.4 字段
字段相当于是类内部声明的变量。
如果在声明字段时没有使用第6.3节中所讲述的“访问级别”限定词,而是使用Dim来声明,Dim语句等同Private。
除了“访问级别”限定词外,声明字段时还可以使用ReadOnly和WriteOnly限定词,前者表示这个字段只读,后者表示这个字段只写。
【例 6.1】【项目:code6-001】使用类的字段。
类代码:
Public Class clsPerson
Public name As String
Public ReadOnly birth As Date = Now
End Class
模块中的调用代码:
Module Module1
Sub Main()
Dim person As New clsPerson
person.name = "李晓明"
Console.WriteLine(person.birth)
person.birth = New Date(1980, 10, 1)
Console.ReadKey()
End Sub
End Module
其中birth字段是一个只读字段,VB.Net编辑器会提示以下代码有错误:
person.birth = New Date(1980, 10, 1)
6.5 属性
可以将属性看作更智能的字段。属性使用Property关键词来声明。
例如,clsPerson类中声明gender属性可以使用以下语句:
Public Property gender As String
上述语句是以下代码段的简化:
Public Property gender As String
Get
End Get
Set(value As String)
End Set
End Property
事实上在老版本的VB.Net中只能使用下面的代码段来声明属性。
Get……End Get代码段是返回值。
Set……End Set代码段是将值设置给该属性。
通常而言,简化的属性代码(上面的代码)同字段用法差不多,但是复杂的属性代码(下面的代码段)更能控制输入输出的值。
注意:属性的声明可以省略Public,默认是公共的,但是在代码中最好显式地加上Public。
【例 6.2】【项目:code6-002】使用类的属性。
类代码:
Public Class clsPerson
Public name As String
Public ReadOnly birth As Date = Now
Private m_gender As String
Public Property gender As String
Get
Return m_gender
End Get
Set(value As String)
If value = "男" Or value = "man" Then
m_gender = "男"
Else
m_gender = "女"
End If
End Set
End Property
End Class
模块中的调用代码:
Sub Main()
Dim person As New clsPerson
person.gender = "man"
Console.Write(person.gender)
Console.ReadKey()
End Sub
以上代码运行时将输出“男”。
可以考虑将gender属性替换为gender字段,如果输入“man”,输出将仍然是“man”。
与字段一样,属性也可以设置只读(ReadOnly)或只写(WriteOnly)。
可以使用以下两种方式设置只读属性:
Public ReadOnly Property gender As String
或者:
Public ReadOnly Property gender As String
Get
……
End Get
End Property
可以使用以下两种方式设置只写属性:
Public WriteOnly Property gender As String
或者:
Public WriteOnly Property gender As String
Set(value As String)
……
End Set
End Property
6.6 方法
通常类中的过程称为方法。关于方法(过程)的重载、可选参数等请参看第3.9节。
类中有一种比较特殊的方法:构造函数。
构造函数在VB.Net中是使用带参数或不带参数的Sub New()方法,它在创建类的新实例时执行。
可以使用以下方式实例化clsPerson类:
Dim person As clsPerson
person = New clsPerson("杨安斌")
或者使用以下简化的方式:
Dim person As New clsPerson("杨安斌")
注意:不同于C或C++语言,VB.Net没有析构函数,当类的生存周期结束后,VB.Net的垃圾回收机制会自动释放资源。
【例 6.3】【项目:code6-003】使用类的构造函数。
类代码:
Public Class clsPerson
Private name As String
Public ReadOnly birth As Date = Now
Private m_gender As String
Public WriteOnly Property gender As String
Set(value As String)
If value = "男" Or value = "man" Then
m_gender = "男"
Else
m_gender = "女"
End If
End Set
End Property
Sub New(ByVal personname As String)
name = personname
End Sub
Public Sub outName()
Console.WriteLine("姓名:" & name)
End Sub
Public Function getGender() As String
Return m_gender
End Function
End Class
模块中的调用代码:
Sub Main()
Dim person As New clsPerson("杨安斌")
person.gender = "男"
Call person.outName()
Console.WriteLine("性别:" & person.getGender)
Console.ReadKey()
End Sub
运行结果如下图所示:
图6-2 输出人员姓名和性别
6.7 共享成员
共享成员使每个实例都可以使用该成员。而在非共享模式下,每个实例都需要有自己的副本。例如,如果类中有一个变量的值应用于整个应用程序,那么就可以考虑将这个变量设置为共享成员,那么所有该类的实例会访问相同的存储位置。
有些编程语言中,也将共享成员称为“静态成员”。
在VB.Net中使用Shared关键词来显示标识共享成员。例如:
Public Shared count As Integer
还有一种是隐式共享,主要是使用Const语句定义的常量。虽然它们无法声明为 Shared,但它们仍然是共享的。
需要注意的是,共享方法中的代码可以访问共享成员,但是不能访问实例成员。
【例 6.4】【项目:code6-004】使用类的共享成员。
类代码:
Public Class clsPerson
Private name As String
Public ReadOnly birth As Date = Now
'共享字段
Public Shared count As Integer
Private m_gender As String
Public WriteOnly Property gender As String
Set(value As String)
If value = "男" Or value = "man" Then
m_gender = "男"
Else
m_gender = "女"
End If
End Set
End Property
Sub New(ByVal personname As String)
name = personname
'设置共享字段
count += 1
End Sub
Public Sub outName()
Console.WriteLine("姓名:" & name)
End Sub
Public Function getGender() As String
Return m_gender
End Function
'共享方法
Public Shared Function getPersonCount() As Integer
Return count
End Function
End Class
模块中的调用代码:
Sub Main()
Dim person1 As New clsPerson("杨安斌")
Dim person2 As New clsPerson("李海娟")
Console.WriteLine("实例化了 " & clsPerson.count & " 个对象")
Console.WriteLine("实例化了 " & person2.getPersonCount & " 个对象")
Console.ReadKey()
End Sub
如果在已经实例化的对象中访问共享成员,那么VB.Net编辑器会警告:通过实例访问共享成员、常量成员、枚举成员或嵌套类型;将不计算限定表达式。
图6-3 警告实例访问
建议不要使用实例访问共享成员,而应该直接使用类名.共享成员的方式。
6.8 运算符重载
类中可以使用Operator关键词和Shared关键词来定义运算符(如+、-、*、/、\\、isTrue、IsFalse、>、<、And、Or、Xor等等)。
【例 6.5】【项目:code6-005】运算符重载。
以下代码将实现-(减号)运算符重载。两个类相减,将会把第一个类中的字符串成员与第二个类中字符串成员相同的字符串删除。
类代码:
Public Class clsOperator
Private stringToOpe As String
Public Sub New(ByVal stringToOpe As String)
Me.stringToOpe = stringToOpe
End Sub
Public Shared Operator -(ByVal firstString As clsOperator, ByVal secondString As clsOperator) As String
Return firstString.stringToOpe.Replace(secondString.stringToOpe, "")
End Operator
End Class
模块中的调用代码:
Sub Main()
Dim firstString As New clsOperator("the quick brown fox jumps over the lazy dog")
Dim secondString As New clsOperator("the")
Console.WriteLine("输出:" & firstString - secondString)
Console.ReadKey()
End Sub
运行结果如下图所示:
图6-4 运算符重载计算结果
注意:一些运算符必须成对定义,例如<(小于)和>(大于)、=(等于)和<>(不等)、isTrue和isFalse等等。
6.9 事件
windows系统是消息驱动型的系统,消息引发事件,事件反馈处理,整个系统的运行就是围绕消息的处理进行的。
事件使用Event关键词来声明,并使用RaiseEvent关键词来触发事件。
例如以下语句为Cat类定义了“捉老鼠”事件:
Event oncatchmouse()
在代码中使用以下语句来触发“捉老鼠”事件:
RaiseEvent oncatchmouse()
注意:事件的声明,必须是在类、结构、模块或接口中,不能是源文件、命名空间、过程或块中。
当在类中定义了事件后,在主代码中可以有以下方法调用事件:
1、在类或模块级别定义变量时,使用WithEvents关键词。
例如以下代码(详细代码请看【项目:code6-006】):
Module Module1
Dim WithEvents mycat As Cat
Sub Main()
使用WithEvents声明了一个Cat类实例。当输入完毕该句代码后,可以看到代码窗口的顶端,第二栏中加入了该类,同时,在第三栏出现对应Cat类的事件。
图6-5 第二栏出现mycat
图6-6 第三栏出现Cat类的事件
当点击第三栏中的事件名称就出现对应事件代码。
【例 6.6】【项目:code6-006】使用事件。
类代码:
Public Class Cat
'私有变量:体重
Private weight As Single
'公共属性:体重,避免用户直接操作猫的体重
Public Property catweight As Single
Set(value As Single)
weight = value
End Set
Get
Return weight
End Get
End Property
'公共字段:名字
Public catname As String
'事件:挠痒痒
Event ontickle(ByVal tickletimes As Integer)
'事件:捉老鼠
Event oncatchmouse()
'构造函数:参数为猫的名字
Sub New(ByVal catName As String)
Me.catname = catName
End Sub
'方法:喂食
Public Function beFeeded(ByVal somefood As String, ByVal foodweight As Integer) As String
If weight > 15000 Then
Return "你家主子目前想减肥,拒绝你的食物。它现在重:" & weight / 1000 & "千克"
Else
weight += foodweight * 0.1
Return "你家主子吃了你贡献的" & somefood & ",它很满意。它现在重:" & weight / 1000 & "千克"
End If
End Function
'方法:跑步,其中一定几率触发捉老鼠事件
Public Function run() As String
If (weight / 1000) < 10 Then Return "你家主子已经很瘦,它拒绝跑步。"
Dim rnd As New Random
Dim runDistance As Integer
runDistance = rnd.Next(11)
'十分之一的概率触发捉到老鼠事件
If runDistance = 10 Then
RaiseEvent oncatchmouse()
Else
weight = weight - runDistance * 400
Return "你家主子跑了" & runDistance & "公里距离。它现在重:" & weight / 1000 & "千克"
End If
End Function
'方法:挠痒痒,触发挠痒痒事件
Public Sub beTickled(ByVal tickletimes As Integer)
'触发挠痒痒事件
RaiseEvent ontickle(tickletimes)
End Sub
End Class
模块中的调用代码:
'定义一个带事件的猫类
Dim WithEvents mycat As Cat
Sub Main()
'使用猫咪名字实例化猫
mycat = New Cat("喵喵")
'设置猫的初始体重
mycat.catweight = 14000
Console.WriteLine("你家主子 " & mycat.catname & " 今日来到你的房间")
Dim command As String
Do While True
command = Console.ReadLine()
'处理不同指令
Select Case command.ToUpper
Case "RUN"
Console.WriteLine(mycat.run())
Case "TICKLE"
mycat.beTickled(2)
Case "FISH"
Console.WriteLine(mycat.beFeeded("鱼", 20000))
Case "WEIGHT"
Console.WriteLine("你家主子现在重 " & mycat.catweight / 1000 & "千克")
Case "HELP"
Console.WriteLine("可以用的指令:run tickle fish weight help quit")
Case "QUIT"
Exit Do
End Select
Loop
Console.WriteLine("完美的一天结束了,明天继续。")
Console.ReadKey()
End Sub
'捉老鼠事件
Private Sub mycat_oncatchmouse() Handles mycat.oncatchmouse
Console.WriteLine("你家主子抓到了一只老鼠放在你面前。")
End Sub
'挠痒痒事件
Private Sub mycat_ontickle(tickletimes As Integer) Handles mycat.ontickle
Console.WriteLine("你抚摸了主子" & tickletimes & "次,它和你的感情更进一步了。")
End Sub
运行结果如下图所示:
图6-7 使用WithEvents处理事件
从上面的代码也可以看到,当使用WithEvents关键词声明变量后,可以使用方法后面加上 Handles关键词+类实例名称.类事件来处理事件。
需要注意的是,处理事件的方法所需参数必须和类事件的参数保持一致。
2、使用AddHandler关键词增加事件,使用RemoveHandler移除事件。
使用AddHandler增加事件的语法为:
AddHandler 类实例名称.类事件, AddressOf 方法名称
使用RemoveHandler移除事件的语法为:
RemoveHandler类实例名称.类事件, AddressOf 方法名称
注意:方法名称的参数必须和类事件的参数一致。
【例 6.7】【项目:code6-007】使用AddHandler和RemoveHandler处理事件。
类代码:
同【项目:code6-006】。
模块中的调用代码:
'定义一个Cat类
Dim mycat As Cat
Sub Main()
'使用猫咪名字实例化猫
mycat = New Cat("喵喵")
'增加捉老鼠事件
AddHandler mycat.oncatchmouse, AddressOf catchmouse
'增加挠痒痒事件
AddHandler mycat.ontickle, AddressOf tickle
mycat.catweight = 14000
Console.WriteLine("你家主子 " & mycat.catname & " 今日来到你的房间")
Dim command As String
Do While True
command = Console.ReadLine()
'处理不同指令
Select Case command.ToUpper
Case "RUN"
Console.WriteLine(mycat.run())
Case "TICKLE"
mycat.beTickled(2)
Case "FISH"
Console.WriteLine(mycat.beFeeded("鱼", 20000))
Case "WEIGHT"
Console.WriteLine("你家主子现在重 " & mycat.catweight / 1000 & "千克")
Case "HELP"
Console.WriteLine("可以用的指令:run tickle fish weight help quit")
Case "QUIT"
Exit Do
End Select
Loop
Console.WriteLine("完美的一天结束了,明天继续。")
Console.ReadKey()
End Sub
'捉老鼠事件
Private Sub catchmouse()
Console.WriteLine("你家主子抓到了一只老鼠放在你面前。")
End Sub
'挠痒痒事件
Private Sub tickle(tickletimes As Integer)
Console.WriteLine("你抚摸了主子" & tickletimes & "次,它和你的感情更进一步了。")
'移除挠痒痒事件
RemoveHandler mycat.ontickle, AddressOf tickle
End Sub
运行结果同【项目:code6-006】略有不同,在程序运行后,输入“tickle”,此时将引发tickle(挠痒痒)事件,然后会将该事件移除。之后再输入“tickle”,不会引发tickle(挠痒痒)事件:
图6-8 使用AddHandler和RemoveHandler处理事件
6.10 Me关键词
当建立类后,在类中如何引用类的当前实例?这时候就需要Me关键词。
Me关键字为引用代码正在运行的类或结构的特定实例提供了一条途径。在向另一个类、结构或模块中的过程传递关于某个类或结构的当前执行实例的信息时,使用Me尤其有用。
例如在Cat类中有个方法:
Private Sub printCatWeight(ByVal currentCat As Cat)
Console.WriteLine(currentCat.weight)
End Sub
如果在Cat类中调用printCatWeight方法,需要传递当前实例化的Cat类对象给printCatWeight方法,显而易见的是不能使用以下语句:
Call printCatWeight(Cat)
因为Cat并不是一个实例对象,此时需要使用以下语句:
Call printCatWeight(Me)
注意:C++、C#、javascript在类中使用自身实例,使用的是this关键词。
6.11 继承
继承允许基于现有类创建新类,新类继承父类的属性、方法和事件等,并可以附加新属性、方法和事件。类的继承在现实世界中也是很普遍的。例如在本章开头所讲的Cat(猫)类继承了哺乳动物的特征,而DragonLi(狸花猫)类也继承了猫类的特征。
通常而言,Cat类和DragonLi类,称Cat为基类,DragonLi为派生类,或者称Cat为父类,DragonLi为子类。
DragonLi除了具有Cat的所有字段、属性、方法和事件外,自身还可以拥有新的字段、属性、方法和事件。
当子类继承父类时,应使用Inherits关键词。以下代码创建DragonLi(狸花猫)类,它继承于Cat(猫)类:
Public Class DragonLi
Inherits Cat
……
End Class
对于类的方法,如果在子类中需要重写,如果与父类同名称同签名(参数个数、参数类型和返回类型相同),那么需要在父类的方法定义语句中加入Overridable关键词,在子类的方法定义语句中加入Overrides关键词。不加入上述关键词,VB.Net识别到后会在子类的方法名称处显示警告(绿色下划波浪线),但也是可以运行的,
注意:书写代码时,要注意Overrides(重写)和Overloads(重载)不要输入错了。关于Overloads请参看第3.9.5节。
【例 6.8】【项目:code6-008】类的继承。
Cat类代码:
Public Overridable Function befeeded(ByVal foodweight As Integer) As String
……同【项目:code6-006】
End Function
Public Function beFeeded(ByVal somefood As String, ByVal foodweight As Integer) As String
……同【项目:code6-006】
End Function
其余代码同【项目:code6-006】。
DragonLi类代码:
Public Class DragonLi
Inherits Cat
'毛颜色
Property fur As String
Sub New(ByVal catname As String)
MyBase.New(catname)
End Sub
Public Function sleep(ByVal times As Integer) As String
catweight += times * 1000
Return "你家主子睡了 " & times & "小时。它现在重:" & catweight / 1000 & "千克"
End Function
Public Overrides Function befeeded(ByVal foodweight As Integer) As String
If catweight > 15000 Then
Return "你家主子舔了舔它" & fur & "的毛,拒绝了你的食物。"
Else
catweight += foodweight * 0.2
Return "你家主子吃了你贡献的高能食物,它很满意。它现在重:" & catweight / 1000 & "千克"
End If
End Function
Public Function run() As String
If (catweight / 1000) < 10 Then Return "你家主子已经很瘦,它拒绝跑步。"
Dim rnd As New Random
Dim runDistance As Integer
runDistance = rnd.Next(11)
catweight = catweight - runDistance * 1000
Return "你家主子跑了" & runDistance & "公里后减少重量:" & runDistance & "千克"
End Function
End Class
模块中的调用代码:
Dim WithEvents mycat As DragonLi
Sub Main()
mycat = New DragonLi("喵喵")
mycat.catweight = 14000
mycat.fur = "黄白相间"
Console.WriteLine("你家主子 " & mycat.catname & " 今日来到你的房间")
Dim command As String
Do While True
command = Console.ReadLine()
Select Case command.ToUpper
Case "RUN"
Console.WriteLine(mycat.run())
Case "TICKLE"
mycat.beTickled(2)
Case "FEED"
Console.WriteLine(mycat.befeeded(20000))
Case "FISH"
Console.WriteLine(mycat.beFeeded("鱼", 20000))
Case "SLEEP"
Console.WriteLine(mycat.sleep(2))
Case "WEIGHT"
Console.WriteLine("你家主子现在重 " & mycat.catweight / 1000 & "千克")
Case "HELP"
Console.WriteLine("可以用的指令:run tickle feed fish help quit sleep")
Case "QUIT"
Exit Do
End Select
Loop
Console.WriteLine("完美的一天结束了,明天继续。")
Console.ReadKey()
End Sub
Private Sub mycat_oncatchmouse() Handles mycat.oncatchmouse
Console.WriteLine("你家主子抓到了一只老鼠放在你面前。")
End Sub
Private Sub mycat_ontickle(tickletimes As Integer) Handles mycat.ontickle
Console.WriteLine("你抚摸了主子" & tickletimes & "次,它和你的感情更进一步了。")
End Sub
运行结果如下图所示:
图6-9 类的继承
6.11.1 MyBase
MyBase代表父类本身。当需要访问父类中被重写或被隐藏的成员时,就需要使用MyBase关键词。
【例 6.9】【项目:code6-009】子类中使用MyBase。
全部代码同【项目:code6-009】。
请将DragonLi类代码中befeeded方法修改为:
Public Overrides Function befeeded(ByVal foodweight As Integer) As String
Return MyBase.beFeeded("猫粮", foodweight)
End Function
执行子类的befeeded方法时,会调用父类中的beFeeded(String, Integer)方法。
6.11.2 MyClass
MyClass可以引用最初的类,当调用MyClass的方法时,将会设置该方法为不可继承,即在继承类中。。。。
【例 6.10】【项目:code6-010】使用MyClass。
Module Module1
Sub Main()
Dim child As New childClass
child.getMeName()
child.getMyClassName()
Console.ReadKey()
End Sub
End Module
Class fatherClass
Public Overridable Sub getName()
Console.WriteLine("获得父类的名称")
End Sub
Public Sub getMeName()
Me.getName()
End Sub
Public Sub getMyClassName()
MyClass.getName()
End Sub
End Class
Class childClass
Inherits fatherClass
Public Overrides Sub getName()
Console.WriteLine("获得子类的名称")
End Sub
End Class
运行结果如下图所示:
图6-10 MyClass的使用
在【例 6.10】中,childClass继承于fatherClass,也就继承了getMeName和getMyClassName方法,但是这两个方法内的代码略有不同:getMeName调用Me.getName方法,也就是childClass类中的getName;而getMyClassName调用MyClass.getName方法,也就是调用fatherClass类中的getName。
6.11.3 构造函数
当父类没有显示使用Sub New()来声明构造函数时,子类可以显示适用或者不使用Sub New()来声明构造函数。
当父类显示使用Sub New()来声明构造函数,子类必须显示使用Sub New()来声明自己的构造函数,构造函数中参数签名(参数个数和类型)可以和父类不同,但是,在子类构造函数的第一句必须是对父类构造函数的调用。参看【项目:code6-008】和【项目:code6-009】。
6.11.4 其它几个关键词
1、NotInheritable
出于某些原因(比如安全因素)考虑,如果希望某个类不被继承,那么在定义类时使用NotInheritable关键词。如:
Public NotInheritable Class Cat
此时DragonLi类将不能从Cat类继承。
2、MustInherit
当某个类不允许直接使用时,可以MustInherit关键词,使子类必须继承父类,而在具体的代码中只能通过子类才能调用父类的成员。如:
Public MustInherit Class Cat
在代码中使用以下语句:
Dim mycat As New Cat("喵喵")
会提示错误:
"New" 不能在声明为 "MustInherit" 的类上使用。
3、MustOverride
父类中可以使用MustOverride来声明一个成员,子类中必须对其重写。
如在Cat类中声明了一个必须重写的jump方法:
Public MustOverride Function jump() As String
如果在DragonLi类中没有该方法,那么VB.Net会提示以下错误:
类“DragonLi”必须声明为“MustInherit”或重写以下继承的“MustOverride”成员。
需要注意的是,如果使用了MustOverride关键词,那么必须省略End Property、End Sub、End Function等关键词。
6.12 命名空间
命名空间是一种命名方案,它将某些功能相似的类组织在一起。命名空间下可以嵌套别的命名空间。
VB.Net下有很多命名空间,例如Microsoft.VisualBasic 命名空间包含支持Visual Basic运行时的类;System.Drawing命名空间包含绘图相关的类;System.IO命名空间包含文件和文件夹读写操作相关类;System.Net 命名空间包含网络操作相关的类……。
由于大多数类都属于某个命名空间下面,在声明使用类时,应该使用命名空间.类名,例如声明一个Dns类:
Dim mydns As System.Net.Dns
由于每次声明或引用都需要加上命名空间名称,导致输入很多、代码很长。通常,可以使用Imports关键词来简化操作。在使用命名空间时,在模块、窗体、类的所有代码最前面加上:Imports 命名空间名称,这样可以减少代码中使用该命名空间下某个类名称的长度。例如在
Module Module1
之前加上:
Imports System.Net
然后在后面的代码中就可以直接使用Dns类:
Dim mydns As Dns
每个VB.Net的工程项目都有一个根命名空间,通常它的名称和项目名称相同,也可以在项目属性页面修改根命名空间的名称。
如果需要使用自定义命名空间,请使用Namespace …… End Namespace语句。Namespace总是具有Public访问级别。
【例 6.11】【项目:code6-011】自定义命名空间。
Namespace animal
Class cat
Sub New(ByVal name As String)
……
End Sub
End Class
Class dog
Sub New(ByVal name As String)
……
End Sub
End Class
End Namespace
在主程序中如果要定义一个cat类,那么使用以下语句:
Dim mycat As New animal.cat("小花")
因为animal属于项目自身的命名空间,不能使用Imports语句来简化。但是,可以在Namespace语句中使用Global关键词声明该命名空间在项目的根命名空间之外:
Namespace Global.plant
Class peach
Sub New(ByVal name As String)
End Sub
End Class
Class Pine
Sub New(ByVal name As String)
End Sub
End Class
End Namespace
在主程序中定义一个peach类,可以在所有代码前加上
Imports plant
然后在代码中使用以下语句:
Dim mypeach As New peach("桃树")
由于.net平台下C#和vb.NET很相似,本文也可以为C#爱好者提供参考。
学习更多vb.net知识,请参看 vb.net 教程 目录
以上是关于教程 类和对象的主要内容,如果未能解决你的问题,请参考以下文章