源文:http://www.cnblogs.com/iswszheng/archive/2009/01/05/1369791.html
对于这几个keyword,虽然看了书,明白了意思,但是在写程序老是把它们搞混淆。记在这里,方便自己随时查看。
先是基本概念:
overloads(重载):与现有成员相同的名称来声明属性或方法,但参数列表与原始成员不同;
overrides(重写):将重写从基类继承的成员;
Overridable(可覆盖的):指定属性或过程可由派生类中同名的属性或过程进行重写;
shadows:隐藏基类中一个同名元素或一组重载元素。
Overloads
之前是一直很confuse,在VS里写代码的时候貌似都没用过overloads,后来查了资料才知道Overloads是VB.NET beta 版遗留下来的关键字,现在已经可以不用写了,仍然存在是为了兼容已有的beta版代码。 其基本用法如下:
Public Overloads Sub a()
Debug.Writeline("a()")
End Sub
Public Overloads Sub a(ByVal para1 As Integer)
Debug.Writeline("a(ByVal para1 As Integer)")
End Sub
Public Sub Demo()
a()
a(1)
End Sub
(此例说明Overloads的作用,就是允许同名函数的存在,前提是有不同的参数。)
在VS里,overloads很多时候都可以省略不写,不过在一些涉及继承方面的内容时,还是需要用到overloads的。在子类中我们希望添加一个重载方法,增强子类功能时候,亦即重载基类中地方法时,就需要用到Overloads. 如下例子:
'基类
Public Class Person
private mName as string
private mBirthday as Date
Public Property Name() as String
Get
Return mName
End Get
Set(Byval value as string)
mName = value
End Set
End Property
Public Property Birthday() as String
Get
Return mBirthday
End Get
Set(Byval value as string)
mBirthday = value
End Set
End Property
End Class
'子类
Public Class Employee
Inherts Person
Private mHireDate as Date
Private mSalary as Double
Private mNames as New Generic.Dictionary(of NameTypes,String)
Public Property Name(byval 1 as NameTypes) as String
Get
Return mNames(type)
End Get
Set(Byval value as string)
if mNames.ContainsKey(type) then
mNames.Item(type)=value
Else
mNames.Add(type,value)
end if
End Set
End Property
End Class
'(如果这里省略了Overload关键字,Name方法的信实现代码就会遮蔽原来的实现代码)
Overridable, Overrides and shadow
在.NET中实现多态有两种方式,覆盖(overrides)和投影(shadow),而投影又分为Shados by Name(就是我们一般用的shadows)和Shadows by
signature(参数序列).
Public Class TheBase
Public Overridable Sub a()
Debug.Writeline("TheBase")
End Sub
End Class
Public Class TheInherited
Inherits TheBase
Public Overrides Sub a()
Debug.Writeline("TheInherited")
End Sub
End Class
Public Class TheShadowed
Inherits TheInherited
Public Shadows Sub a()
Debug.Writeline("TheShadowed")
End Sub
End Class
'情况一:
Dim c As TheBase
c = New TheBase()
c.a() ' 输出 TheBase
c = New TheInherited()
c.a() ' 输出 TheInherited
c = New TheShadowed()
c.a() ' 输出 TheInherited
'情况二:
Dim c As TheInherited
c = New TheBase()
c.a() ' 错误!无效的转换。
c = New TheInherited()
c.a() ' 输出 TheInherited
c = New TheShadowed()
c.a() ' 输出 TheInherited
'情况三:
Dim c As TheShadowed
c = New TheBase()
c.a() ' 错误!无效的转换。
c = New TheInherited()
c.a() ' 错误!无效的转换。
c = New TheShadowed()
c.a() ' 输出 TheShadowed
此例说明Overridable、Overrides、Shadows的用法。
请注意TheBase里面的Overridable,如果没有这一句,后面类TheInherited将无法声明同名过程a(),而TheShadows仍然可以。
Overridable 的意思是:可以被重写的。默认情况下,似乎不能重写基类中方法的行为的,基类必须显式地使用Overridable关键字,指出允许重写地方法。
Overrides 的意思是:重写原来的,一般用于子类重写父类的方法。如果没有Overrides关键字,当实现一个与基类中某一方法同名同参数地方法时,会得到一个编译错误。
Shadows 的意思是: 指示该变量隐藏基类中的同名编程元素或重载元素集。任何类型的声明元素均可用其他任何类型来隐藏。隐藏的元素在隐藏它的派生类中不可用。仅可以在模块、命名空间或文件级中使用 Shadows。这意味着可以在源文件中或者在模块、类或结构内(但不在过程内)声明隐藏变量。如果指定了 Shadows,也可以省略Dim关键字。不能在同一变量声明中同时指定 Static 和 Shadows。
在运行的例子中我们可以清晰地看到,无论变量c的定义是什么,VB.NET都会尽量寻找到最后被定义的那个成员。也就是说,如果被重写了,那么就找“从变量类型开始,到这个变量所指对象实际上的类为止,最后一次被重写(Overrides)的那个成员”。(当然,如果找不到,那么还会往变量类型的祖先那个方向上去找。)
简单点讲就是说,无论c怎么定以,如果他指向的是一个TheBase,他就找“到TheBase为止最后一次被重写的那个Sub a()”。如果他指向的是一个TheInherited,就找“到TheInherited为止最后一次被重写的那个Sub a()”,也就是TheInherited里面的那个。
对于TheShadowed来说,情况稍微复杂一点:
由于TheShadowed里面所写的那个a()被声明为Shadows的,也就是说这个a()跟TheBase和TheInherited里面的没有关系,于是从变量c的基类(TheBase)开始找,一直找到变量所指对象的类型TheShadowed,发现变量c的类型(无论是TheBase还是TheInherited)里面的那个a()最后一次被重写是在TheInherited里面(注意:TheShadows里面的a()跟它没关系),于是只要c不是Dim .. As TheShadows,那么就会选择调用TheInherited里面的a()了。