博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
类 的重载(Overloads)与隐藏(Shadows)
阅读量:5324 次
发布时间:2019-06-14

本文共 4082 字,大约阅读时间需要 13 分钟。

       我在上篇文章中讲解了类 的继承和重写,如果想要在派生类中重写基类了方法或函数,那首先基类必须要有用 Overridable 关键字的公开声明的方法或函数,这样,基类的派生类才能用 Overrides 关键字来重写基类带有 Overridable 关键字的公开方法或函数。

      重载是什么意思呢?

      重载(Overloads): 就是我们可以用同样的名称,在派生类中用不同的参数列表来创建多个方法和属性,在调用时就可以适应不同参数类型的要求。

       呵呵...那好,我们来看一下,这样的写法会有什么结果:

Module Module1    Public Class baseClass        Public Function CountY() As Integer            CountY = 100        End Function    End Class    Private Class derivedClass        Inherits baseClass        Public Overloads Function CountY(ByVal i As Integer) As Integer            CountY = i * 2        End Function    End ClassEnd Module

        好!基类和派生类写好了,派生类中也重载了基类的 ConutY 函数,那我们就来实例化派生类,并使用它的函数看看什么情况:

       呵呵,看到了吧,居然有两个 CountY 函数,一个无参数的和一个有参数的!!为什么会这样呢?基类的无参数 CountY 函数怎么会出现在派生类的对象中?

         没错 ,我在类的继承和重写的文章中讲到,派生类具有继承基类所以公共成员的能力,你再看基类的 CountY 函数,发现了吧,它用的是Public 关键字声明的,这是公开性的函数。所以...

        另外:还记得上篇文章也介绍“显式编写构造函数 New 的事” ,我用了一个 mybase.new() 继承了基类的性质。现在没有写,其实是一种默认的隐式调用。

        所以现在的派生类应该是内含两个 CountY 函数了,无参数的 CountY 其实就是基类的方法,是由于 Overloads 和 Mybase.new() 双重作用的影响。

        那再看这样的变化情况。我们在派生类中添加一个用 Overloads 标识的与基类形式一致的无参数 CountY 后,再执行会出现什么情况:

Module Module1    Public Class baseClass        Public Function CountY() As Integer            CountY = 100        End Function    End Class    Private Class derivedClass        Inherits baseClass        Public Overloads Function CountY(ByVal i As Integer) As Integer            CountY = i * 2        End Function        Public Overloads Function CountY() As Integer            CountY = 200        End Function    End Class    Sub main()        Dim obj As New derivedClass        Console.WriteLine("带参数的 CountY 函数的返回值为:{0} ", obj.CountY(10))        Console.WriteLine("无参数的 CountY 函数的返回值为:{0} ", obj.CountY())        Console.Read()    End SubEnd Module

        我们来看看结果:

怎么样,是不是很好奇,为什么是执行的派生类中的无参数函数 CountY ,而不是执行的基类中的无参数函数 CountY ?

其实这也可以叫隐藏(Shadows)!

我们用 Overloads 重载方式隐藏了基类的同名方法,以防用户发生混淆。

Shadows功能很强的。

Private Class derivedClass        Inherits baseClass        Public Shadows Function CountY(ByVal i As Integer) As Integer            CountY = i * 2        End FunctionEnd Class

      我们用Shadows 关键字代替Overloads 来实现重载后,看看会出现几个 CountY 函数:

      看到了吧,只有一个了!我们看运行结果:

Sub main()    Dim obj As New derivedClass    Console.WriteLine("带参数的 CountY 函数的返回值为:{0}", obj.CountY(50))End Sub

      如图:

      哈,基类的方法看不到了。但是,这和重写的效果岂不是一样了吗?

      如果是一样的作用,要 Shadows 干什么呀。

      其实还是有区别的。最明显的区别在于,隐藏适用于任何元素类型,你可以在派生类中用:

         Public Shadows CountY as Integer

     来隐藏基类的 CountY() 方法;而重写只能适用于方法与属性,而且声明参数与修饰符都要求完全一致。

      还要注意一点,当派生类又派生出一个子类时,重写与隐藏都会被继承下去。当然,如果在派生类中是用 private 来修饰 Shadows 成员的话,它的子类就会继承它基类的成员了。

 

隐藏(Shadows)

      一般来说,隐藏有两种情况:一种是通过范围来实现。比如你定义一个全局变量 x,但在一个方法中 ,你又定义了一个局部变量 x,在方法中使用 x 时,使用的是局部变量的那一个, 也就是局部变量 x 在方法中隐藏了全局变量x(这里牵涉到作用域的概念,所以这个比如不是很恰当);另一种情况,就是通过继承来隐藏。方法么,除了刚才用的 overloads,还可以用 Shadows 关键字来实现。Shadows(遮蔽、阴影),倒是很贴切的名字。

        隐藏就如同作用域一样,全局变量在过程中被局部同名变量隐藏。

       如果基类设计有误而又无法得到源码,或者基类适用大多情况,但有特殊情况时又得改写。由于基类中方法设计时就是不允许重写(没有 Overridable ),这里想在子类中“改写”这个方法,怎么办?当然是用 Shadows 来隐藏基类的同名方法。

         简单地说:

       重写是征得(Overridable)允许后的改写;而隐藏则是未经允许就强行改写基类的方法。

        当声明一个方法,如果不是用 Overrides 关键字,它就是非虚拟方法,而非虚拟方法是不能被子类重写和替代的方法。

        而隐藏就是这样,它要重写非虚拟方法,不管它们是否声明时使用了 Overridable ,它无视规则。

         所以,隐藏比重写更血腥,如果说重写是有法有依的司法人员,那么隐藏就是无法无天的抢劫犯。

         因此隐藏打破了规则,基类开发人员在把方法标记或不标记 Overridable 时总是很小心,确保方法在子类是否重写,以

         保证基类能够继续正常使用。常常没有标记 Overridable 的不希望重写,而 Shadows 却打破了这个规则。

          然而,使用Shadows根本上改变了Employee的功能,便它不再是Person对象,这种本质上背离正常期望的方法会

          引发错误,并使得代码难于理解和维护。

          所以隐藏方法是一个危险的方法!!!

          看例子,先在Person中定义非虚拟方法---只读Age,使其故意为负,以便在子类中改正:

 
 
 

      如图:

      那我们在子类 DerivedClass 中来隐藏基类的错误算法,写个正确的来代替:

 
 
 
 

        注意:Shadows 是可省略的,但IDE会警告,最好加上。隐藏发生在方法签名相同的情况中。

      错误警告如图:

        注意:这里派生类的 Age 属性,并不是重写基类的 Age 属性。属性没有重写一这说法!只有方法才能重写 。

        如果派生类中有了和基类中某个属性的名称相同的属性,这时,派生类就是隐藏了基类的属性,只让派生类中同名的属性有效。 

       我们来看下结果:

      结果为正数的年份,所以,调用的是派生类 DerivedClass 的 Age 属性,因为此属性用 Shadows 关键字隐藏了基类的错误属性。

     Shadows 是一个怪兽,它可以改变原来的只读为可读写:

 
 

        可以看去有 Shadows 在,给只读的属性增加可写的功能也能实现…

       但这样使得使用时会发生意想不到的问题,下面变量改为类型 BaseClass,所以 Age 只能为只读,所以提示出错:

        如果更为极端时,Shadows这个怪兽还可以把方法变成实例变量、或将属性变成方法。

        比如在子类 DerivedClass 中把 Age 变成下面:

         Public  Shadows  Age  As String

        这都说明了 Shadows 在隐藏基类元素时,子类会改变其牲或作用域。

         说到作用域,隐藏实际上就是作用域的情况,局部变量隐藏全局变量,使得全局变量在过程中失效一样:

       现在 VB.NET 对继承的处理功能真的很强大,继承层次体系是有很多好处,但是事物总是有其双面性 ,继承也有不少问题,其中最麻烦的,就是 “ 基类的脆弱之处 ”。

下篇文章将继续解说....

转载于:https://www.cnblogs.com/lfls128/p/4972292.html

你可能感兴趣的文章
QQ在线客服,默认到要加好友,授权也不起作用需要先开通QQ营销服务
查看>>
pro git
查看>>
UVA 11825 Hackers’ Crackdown(集合动态规划 子集枚举)
查看>>
【转载】初涉职场的40句金玉良言
查看>>
Django使用Mysql数据库已经存在的数据表方法
查看>>
Python-类进阶
查看>>
php函数的参数引用变量
查看>>
统计题量
查看>>
WCF 异步调用问题
查看>>
小白成长之路:初识python(六) --python线程池
查看>>
C#委托的介绍(delegate、Action、Func、predicate)
查看>>
mtk Android 编译命令自定义--添加版本号
查看>>
android 串口调试
查看>>
2009年北京航空航天大学计算机研究生机试真题,数组排序
查看>>
蓝牙地址的规则
查看>>
python 检查内存
查看>>
【积累】各浏览器之间的差异
查看>>
去掉所有字符里面的空格换行符等
查看>>
CF 1182F Maximum Sine——根号算法
查看>>
mybaits 学习笔记(搭建)一
查看>>