向美术教师交做业时,一位学生只交了一张白纸。
老师问:”画呢?”
学生答:”这儿?”他指着白纸说。
老师:”你画的是什么?”
学生:”牛吃草。”
老师:”草呢?”
学生:”牛吃光了。”
老师:”牛呢?”
学生:”草吃光了,牛还站在那里干什么?”
ide
1、抽象基类函数
正若有个好爹能够少奋斗二十同样,父类自己是很是有用的,能够进行实例化,也能够不能实例化,作个样子,好处很大。spa
一、MustInheit.net
基类可实例化,但也能够不实例化(或者禁止建立该类的对象),这时,只能建立子类,以及子类的对象。设计
能够用MustInherit来指明该基类不能建立对象。code
注意:这不表示不能声明基类(以下例Person)类型的变量,只是不能用New Peron来建立对象。orm
同时在这个时候,咱们还可继续使用共享办法(由于它只属于类,不属于对象)对象
二、MustOverideblog
指明只能由子类重写的方法(sub,funciton,property),此类方法只有方法头,而无具体的实现代码。所以不能建立对象。继承
故: 类中含有MustOveride时,此类必须由MustInherit进行声明。即:
只能在属性和过程声明语句中使用 MustOverride。 指定 MustOverride 的属性或过程必须是类的成员,而且该类必须标
记为 MustInherit。
Public MustInherit Class Person '只能被继承 Private mName As String Private mBirthDate As Date Private mID As String Public Event NameChanged(ByVal newName As String) Public Event DataChanged(ByVal field As String, ByVal newValue As Object) Public MustOverride Function LifeExpectancy() As Integer '无实现代码,只能被子类重写 '...... End Class
上面声明Mustoveride的函数LifeExpectancy只有方法头,无实现代码,此类方法也称“抽象方法”或“纯虚拟函数”
任何继承此类的子类,必须重写这些抽象方法,不然将产生语法错误,子类也不会编译。
故在子类中添加:
'=======子类Employee中重写基类的纯虚函数=============== Public Overrides Function LifeExpectancy() As Integer Return 90 End Function
三、抽象基类
MustInherit及MustOverride同时出现该类时,此类被称为抽象基类。或者说:含有抽象方法的类叫抽象基类。
抽象基类颇有用,能够前期只架上抽象基类这个架子,每一个子类根据本身状况进行重写适合本身的方法。
注意的是,此时子类都必须有抽象方法的实现代码,不然出错。
Public MustInherit Class AbstractBaseClass Public MustOverride Sub DoSomething() Public MustOverride Sub DoOtherSomething() End Class '接口 Public Interface IAbstractBaseClass Sub DoSomething() Sub DoOtherSomething() End Interface
某些方面,抽象基类与Interface接口概念类似,上面接口IAbstractBaseClass,在实现这接口的类中也必须有其内两个方法
的实现代码,不然同样也会出错。
四、禁止继承
上面是“只能继承”中建立对象。
下面是“禁止继承”,用NotIneritable来讲明此类,不许再进行继承,到此为止!
Public NotInheritable Class officeEmployee '指定基再也不作基类(即再也不向下派生)
不能被继承的类有时被称为“密封”类
2、多接口
接口,如同外交家同样,能够与外界进行交流。
VB.net中,对象能够有一个或多个接口。全部对象都有一个主接口或本地接口,接口由用Public声明的方法、属性、事件、字段。
除本地接口外,对象还可使用Implements来实现辅助接口。
一、对象接口
类中除Private声明的外均可做本地接口。例:
'方法做为接口 Public Sub AMethod() End Sub '属性做为接口 Public Property AProperty() As String End Property 'Event事件做接口 Public Event AEvent() '变量做接口 Public AInteger As Integer
注意:上面无实现代码,由于接口只在于架子的声明,其内的实现代码并非接口的一部分。这是重要的区别!
由于将接口与实现代码区分是面向对象程序设计的核心内容。
使用本地接口
一旦声明了本地接口,就可在对象中用这些接口与外界产生交流。下面类中Pulbic方法,其对象就可直接用它与外界发生联系。
'============类的本地接口========= Public Class TheClass Public Sub DoSomething() '..... End Sub Public Sub DoOtherSomething() '....... End Sub End Class '==========主程序中使用这两个接口======== Dim myObject As New TheClass myObject.DoSomething() myObject.DoOtherSomething()
二、辅助接口
在设计上,只有同类的对象才有相同的本地接口,这有很大的限制。
若是把一组不一样的对象,它们本地接口各不一样,处理起来就麻烦了。
好比,对于产品 、顾客、发票三类对象,不具备天然的继承关系,可是,咱们须要打印这三个信息,因而,
产生了另外一个概念“辅助接口”,也就平时说的接口,经过这个接口,使三者都可打印。
接口Interface是同Class,Modul同样是同一级别的概念,它象抽象方法同样并不具备实现代码,实现代码都在使用接口
的类中。这样使用接口时,没必要管是否是同一类型对象,都可正常运行。
(1)定义接口
用Interface来定义一个接口,经过添加模块方式,在模块外部添加接口代码:
Public Interface IPrintableObject '接口定义(与Class,Module平级)内部做用域相同 Function Label(ByVal index As Integer) As String '故其前无Public,friend等限定 Function Value(ByVal index As Integer) As String ReadOnly Property Count() As Integer End Interface Module Interfaces End Module
接口定义包含在 Interface 和 End Interface 语句内。
在 Interface 语句后面,能够选择添加列出一个或多个被继承接口的 Inherits 语句。 即接口能够继承。
在声明中,Inherits 语句必须出如今除注释外的全部其余语句以前。
接口定义中其他的语句应该包括 Event、Sub、Function、Property、Interface、Class、Structure 和 Enum 语句。
接口不能包含任何实现代码或与实现代码关联的语句,如 End Sub 或 End Property。
在命名空间中,默认状况下,接口语句为 Friend,但也能够显式声明为 Public 或 Friend。
在类、模块、接口和结构中定义的接口默认为 Public,但也能够显式声明为 Public、Friend、Protected 或 Private。
Shadows 关键字可应用于全部界面成员。 Overloads 关键字可应用于界面定义中声明的 Sub、Function 和 Property 语句。
此外,Property 语句能够具备 Default、ReadOnly 或 WriteOnly 修饰符。 不容许使用任何其余修饰符:Public、Private、
Friend、Protected、Shared、Overrides、MustOverride 或 Overridable。
接口是一个数据类型,相似于类或结构(Struction)。由于能够这样定义这个类型的变量:
Private printable As IPrintableObject
但上面,都没有实现的代码,实现代码都是在类中实现。因此接口是不能直接用New的。
(2)使用接口
用户只须知道接口,没必要了解对象内部细节,就可使用不一样的对象。
窗体中添加方法:
Public Sub PrintObject(obj As IPrintableObject) '窗体内添加例程 Dim index As Integer For index = 0 To obj.Count Debug.Write(obj.Label(index) & ": ") Debug.WriteLine(obj.Value(index)) Next End Sub
而后窗体中添加按钮,并添加代码:
Private Sub ButtonPrint_Click(sender As Object,e As EventArgs) Handles ButtonPrint.Click Dim obj As New Employee() obj.EmployeeNumber = 123 obj.BirthDate = #1/1/1980# obj.HireDate = #1/1/1996# PrintObject(obj) End Sub
点击运行,会提示错误:由于接口只是方法头或事件头,并无具体的实现代码。所以还要在类中添加实现的代码。
(3)实现接口
任何类(除抽象基类)均可以使用Implements来实现接口。
由于接口要用类的对象来传递,使得接口最后言之有物。而抽象基类是不能产生对象的,因此抽象基类是不能有接口的。
加入Implements回车后,会自动把接口各方法或事件的架子添加到类中,咱们只须在内加入实现代码。
类中实现的方法、属性等名称,并不重要,重要的是参数的数据类型及返回值必须与接口定义的类型相匹配。
实现代码以下:
'================Employee类中实现接口(链接到外部接口类型上)========= Implements IPrintableObject '这里按回车后,自动添加Iprintableobject成员,来实现细节 '为接口准备或要使用的字段 Private mLabels() As String = {"ID", "Age", "HireDate"} Private mBirthDate As Date Private mSalary As Double Public ReadOnly Property Count As Integer Implements IPrintableObject.Count Get Return UBound(mLabels) End Get End Property Private Function Label(index As Integer) As String Implements IPrintableObject.Label Return mLabels(index) End Function Public Function Value(index As Integer) As String Implements IPrintableObject.Value Select Case index Case 0 Return CStr(EmployeeNumber) Case 1 Return CStr(Age) Case Else Return Format(HireDate, "Short date") End Select End Function
注意:能够看到实现方法等的后面有Implements IPrintableObject.Label,这相似于Handles,它也能够经过用逗号把
一个接口的多个方法联系到一个方法中,或者多个接口的方法联系到一个方法中。
(实际上就是把函数地址与外界联系了起来,这样使用这个地址,天然就调用了不一样对象中的方法)
看一下整个接口的示意图:
(4)重用 通用的实现代码
辅助接口,能够有几个,几个中能够同一个方法,这个方法就成了通用的方法。
下面两个接口有方法都联系到同一个方法Value(类Employe中)
'=========接口1,有Value================= Public Interface IPrintableObject Function Label(ByVal index As Integer) As String Function Value(ByVal index As Integer) As String ReadOnly Property Count() As Integer End Interface '========接口2,有GetValue=============== Public Interface IVales Function GetValue(ByVal index As Integer) As String End Interface '=======Employee中两接口,同时关联到Value函数上(函数签名与上面相同参数)=========== Implements IPrintableObject Implements IVales Public Function Value(index As Integer) As String Implements IPrintableObject.Value, IVales.GetValue Select Case index Case 0 Return CStr(EmployeeNumber) Case 1 Return CStr(Age) Case Else Return Format(HireDate, "Short date") End Select End Function
能够看到,其后用逗号表示,两个接口都用到Value方法。
(5)合并接口、继承
能够同时合并辅助接口和继承在。
当从一个实现接口的类继承时,新的子类自动得到的接口和基类的实现代码。
若是指定基类方法能够重写,则子类能够重写这些方法。
不只重写基类主接口的实现代码,并且也能够重写接口的实现代码。
Public Overridable Function Value(ByVal index As Integer) As String Implements IPrintableObject.Value, IValues.GetValue
上面表示这个接口实现,是能够被重写的。
完整定义以下:
Public Overridable Function Value(index As Integer) As String Implements IPrintableObject.Value, IVales.GetValue Select Case index Case 0 Return CStr(EmployeeNumber) Case 1 Return CStr(Age) Case Else Return Format(HireDate, "Short date") End Select End Function
注意:因为上面是Public,所以它在主接口(本地接口)中也是有效的。
而且它仍是两个接口中的一部分,意味着能够被三种方式访问。
三种 方式访问:
Dim emp As New Employee("Andy") Dim printable As IPrintableObject = emp Dim values As IVales = emp Debug.WriteLine(emp.Value(0)) Debug.WriteLine(printable.Value(0)) Debug.WriteLine(values.GetValue(0))
第一种:主接口(本地接口)
第二种:IprintableObject接口访问
第三种:IValues接口访问
这样三种接口合并于一身,都在Value这个方法上。
要声明接口方法的实现,可使用任何在实例方法声明上合法的特性(包括 Overloads、Overrides、Overridable、Public、Private、Protected、Friend、Protected Friend、MustOverride、Default 和 Static)。
Shared 特性是不合法的,由于它定义类而不是实例方法。
-----------------------------------------------------------------------------------------------------------------------