如果我在基类中更改了成员的数据类型,以及那些允许重写的那些方法和属性派生类及其子类就无法正常工作。
我们常用的一个方法,就是,把有可能发生的更改全都放在派生类中进行,不在基类中做 。
我们在基类中使用的是抽象类,它内含的方法与属性只有定义,没有进行实现,而把实现部分都放在派生类中做。
我们用MustInherit来修饰类名,使类成为抽象类(基类),在它的成员中,把方法和属性前加入MustOverride修饰符表示它们必须在派生类中加以实现。而在派生类(子类)中使用关键字Overrides重写一个方法的方式。
重写方法和重载方法:
在子类中重写一个方法的方式是,实现一个和基类中方法同名、并带有相同参数列表的方法,然后使用Overrides关键字来表明要重写该方法,如果没有Overrides关键字,当实现一个和基类中某一方法同名的方法时,会得到一个编译错误。
当重载一个方法时,是添加了一个同名、但拥有不同参数列表的新方法,使用Overloads关键字就可以重载基类中的方法。
而在重写一个方法时,是用一个新的实现代码来替换原来的方法。
重载允许增加现有方法的新版本,只要它们的参数列表不同。
重写允许子类用具有同样方法签名的新方法来完全替代基类的实现方法。
若基类要做功能扩展,最安全的方法是添加新成员。一般是往派生类添加设计时缺失的新成员。最好不要使用Overloads关键字来命名与基类相同的成员,那样往往会带给你意想不到的问题。最好重新定义新成员,命名上也要尽量与基类已有的成员名区分开来。(装载)
要使用提供可行的最低访问权限的访问修饰符 声明类成员。
1。内部类成员应声明为 Private
2。仅在类内与派生类才需要的成员应标记为Protected;
3。Friend 数据成员可以从类的外部访问,但仅限于该模块是定义该类的项目的一个组成部分;
3。使用Public标识的成员,只能是实例化时真正需要的内容,而且经常用在类层次结构的底部。
从面向对象的观点来看,接口就是对象的外观,而对象实际的工作方式就是实现。在vb.net中,对象可以有一个或多个接口。所有对象都有一个主接口或本地接口,接口由方法、属性、事件或用public关键字声明的成员变量组成。
接口也可以定义属性、方法和事件。与类不同的是,接口并不提供实现。现在的接口,是由类来实现的,并从类中被定义为单独的实体。
接口表示的是一种约定。实现接口的类必须严格按其定义来实现接口的每个方面。
有了接口,就可以将功能定义为一些紧密相关成员的小组。可以在不危害现有代码的情况下,开发接口的增强型实现,从而使兼容性问题最小化。也可以在任何时候通过开发附加接口和实现来添加新的功能。虽然接口实现可以进化,但接口本身一旦被发布就不能再更改。对已发布的接口进行更改会破坏现有的代码。
若把接口视为约定,很明显约定双方都各有其承担的义务。接口的发布者同意不再更改该接口,接口的实现者则同意严格按设计来实现接口。(—转载)
接口的实现可以是类,也可以是结构。接口的定义用的是Interface关键字,实现时用的是Implements关键字。
将接口从其实现代码中分离出来是面向对象的程序设计的核心内容。
只要声明一个public例程,就可把一个方法作为接口的一部分:
public sub Method()
end sub
在这个例程中并没有代码,任何代码都是实现方式,而不是接口的一部分。
辅助接口:每个实现通用接口的对象必须提供代码,来实现该接口,这根继承不同,不能自动重用基类中的代码。
1.定义接口:在项目的任何代码模块中,可以使用interface关键字定义一个正式接口,但最好讲这种类型的定义放在标准模块里。接口定义了一组方法(sub,fuction,或property)和事件。选择实现该接口的类必须提供这些方法和事件。
代码模块可以包含许多接口的定义,这些定义必须位于任何其他代码块的外部,而不能放到class或是module块中,因为他们对于这些结构是平级的。
必须用public或friend作用域来声明接口。
接口中只定义了方法、和事件(包括参数和数据类型)。并没有实现方法,当用类来实现这个接口,要求每个类为在接口中定义的每个方法提供实现代码。
接口用类或结构来实现,就象一个抽象的类。
2.使用接口:接口定义了方法和事件,如果他们支持该接口(在程序设计要用到所定义的接口),就需要一个对象,以实现该接口。辅助接口的使用方式:将某个对象类型看成是实际的接口类型。
以下为转载内容:
'在模块interface.vb中写入下面的接口定义
Public Interface IHenry
Sub subX(ByVal x As Integer)
Function fcnY(ByVal y As Integer) As Long
Property proZ() As String
End Interface
Public Class CHenry
Implements IHenry '接口的实现,在类中实现接口
Private z1 As String
Sub subX(ByVal x As Integer) Implements IHenry.subX
'填写实现代码
End Sub
Function fcnY(ByVal y As Integer) As Long Implements IHenry.fcnY
'填写实现代码
End Function
Property proZ() As String Implements IHenry.proZ
Get
Return z1
End Get
Set(ByVal Value As String)
z1 = Value
End Set
End Property
End Class
上面的例子知道,在CHenry中实现IHenry 接口,这样接口就可以有任何作为CHenry实例来创建的对象使用。
3.接口的实现方式
为了实现接口,必须实现该接口定义的所有方法和属性
Function fcnY(ByVal y As Integer) As Long Implements IHenry.fcnY
其实名称是次要的,起作用的是Implements子句。唯一的要求是参数的数据类型和返回值的数据类型必须与接口定义的类型相匹配。
这与使用handles子句来表明哪个方法将处理事件非常相似。Implements子句允许
总结:通过接口,我们可以定义下某种对象的基本外观,然后可以自由地进行实现与扩展,却不涉及对原型的直接修改。
在不同的类中实现同一个接口,就是一种用接口实现的多态性,一个接口可以有多个实现的类。并且在类和接口中可以实现多个接口,上面的例子只是实现了一个接口,类中可以实现多个接口。
4。重用通用的实现代码
在同一个接口或不同的接口中,方法能够作为多个方法的实现代码。
'将下面的定义添加到刚才上面的模块接口IHenry.vb中
public Interface IS
Function GetfcnY(ByVal y As Integer) As Long
End Interface
这个方法和上面的fcnY的方法相同。方法名和参数变量名不匹配并不重要,只要参数和返回值的数据类型匹配就行了。
'在类的实现方法里就可以这样写
Public Class CHenry
Implements IHenry '接口的实现,在类中实现接口
Implements IS '接口的实现,在类中实现接口
Function fcnY(ByVal y As Integer) As Long Implements IHenry.fcnY,Implements IS.GetfcnY
'填写实现代码
End Function
这与handles关键字的用法很相似。类中的单个方法,不管作用域和名称是什么,只要参数和返回值的数据类型全部匹配,都可以实现其他接口定义的任意多个方法。
DirectCast和CType之间的区别
DirectCast 关键字引入类型转换操作。该关键字的使用方法与 CType 关键字相同,如下列所示:
Dim Q As Object = 2.37 ' Requires Option Strict to be Off. Dim I As Integer = CType(Q, Integer) ' Succeeds. Dim J As Integer =DirectCast(
Q, Integer)
' Fails.
这两个关键字都将要转换的表达式作为第一个参数,而将要转换成的类型作为第二个参数。如果未定义表达式的数据类型与第二个参数所指定的数据类型之间的转换,那么这两种转换都会失败。
这两个关键字之间的差别在于:只要定义了表达式与类型之间的有效转换,CType 即可成功,而 DirectCast 则要求对象变量的运行时类型与指定的类型相同。不过,如果表达式的指定类型和运行时类型相同,则 DirectCast 的运行时性能比 CType 的运行时性能好。
在上例中,Q
的运行时类型为 Double。CType 因为 Double 可以转换成 Integer 而成功了,DirectCast 则因为 Q
的运行时类型不是 Integer 而失败了。
如果参数类型不匹配,DirectCast 会引发 InvalidCastException 错误。
抽象类和接口(转载)
抽象类是一种不能实例化而必须从中继承的类。
抽象类可以完全实现,但更常见的是部分实现或者根本不实现,从而封装继承类的通用功能,
它可以提供已实现的成员,因此,可以用抽象类确保特定数量的相同功能,但不能用接口这样做。
接口是完全抽象的成员集合,它的成员都无法在接口定义时实现,我们可以将它看作是为操作定义合同,接口的实现完全留给开发者去做。
它们之间的区别:在VB.NET中,类只能是从一个基类继承,所以如果要使用抽象类为一组类提供多态性,这些类必须都是从那个类继承的(这些类要继承基类);接口就不一样了,它不但可以用一个类或结构实现多个接口,一个接口还可以有多个实现。
如果我们要创建某个组件的多个版本(或着说要定义的某个类的多种版本,其中所包含的属性、事件等都不相同。)我们只要通过更新基类(要定义一个抽象类),所有继承类都随更改自动更新。
接口一旦创建就不能更改。如果需要接口的新版本,必须创建一个全新的接口。所以,如果创建的功能将在大范围的全异对象间使用,则使用接口。
在应用程序要求很多可能不相关的对象类型以提供某种功能的情况下,用接口适用性会更强;接口比基类更灵活,因为可以定义单个实现来实现多个接口;在无需从基类继承实现的情况下,接口更好;在无法使用类继承的情况下接口是很有用的。
抽象类主要用于关系密切的对象,而接口最适合为不相关的类提供通用功能。
接口设计原则:
1。“接口不变性”
接口一旦被定义和接受,就必须保持不变,以保护为使用该接口而编写的应用程序。接口发布后,就不能对其进行更改。这是我们进行组件设计的一个重要原则,叫做‘接口不变性’。
创建一个接口就是在创建一个定义,接口定义发布后则永远不能更改。接口不变性,就是为了保护为使用接口而编写的现有系统。当接口设计与需求有所出入,确认需要大幅度变更时,我们应该创建新的接口。一般命名方式是,新接口可以通过在原来的接口名称后追加一个数字‘2’来命名,以显示出它与现有接口的关系。然后通过接口继承来创建新接口。
2.‘接口分解’
把确定哪些属性和方法属于接口的设计过程称为‘接口分解’。基本准则是,应在一个接口中将紧密相关的几个功能聚合为一组。功能太多会使接口不便于运行,而过于细分功能将导致额外的系统开销并降低使用的简易性.
(转载)