类 的重载(Overloads)与隐藏(Shadows)

       我在上篇文章中讲解了类 的继承和重写,如果想要在派生类中重写基类了方法或函数,那首先基类必须要有用 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 Class

End Module

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

1

1

       呵呵,看到了吧,居然有两个 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 Sub

End Module

        我们来看看结果:

1

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

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

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

Shadows功能很强的。

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

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

image

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

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

      如图:

1

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

      如果是一样的作用,要 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,使其故意为负,以便在子类中改正:

 
  
 
 

      如图:

1

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

 
  
 
  
 
 

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

      错误警告如图:

1

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

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

       我们来看下结果:

1

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

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

 
 

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

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

1

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

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

         Public  Shadows  Age  As String

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

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

新建位图图像

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

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值