类 的继承性(Inherits)与 重写(Overrides)

(类) 与 (结构) 类似,让我们可以定义并封装成一组相关项的数据类型。比如封装成结构,那么这个封装包的数据类型就为值类型;如封装成类,那么这个封装包的数据类型就为引用类型。

然而与结构的一个重要区别就是:类可以继承和扩展其他类的特性。

作为新类的基础的类称为“基类”;从基类派生出来的类称为“派生类”。派生类继承基类中定义的所有字段、属性、方法 和事件。我们只要对类进行一次开发和调试,就可以将其作为其他类的基类重复使用。

我们看一段代码:

Module Module1
    Public Class baseClass
        Private x As Integer '类的字段,建议使用字段私有化
        Protected y As Integer '受保护的字段,只有派生类可调用
        Public Sub New() '基类的构造函数
            x = 10
            Console.WriteLine("(1)、基类的 New 构造函数被调用")
        End Sub
        Public Overridable Function GetY(ByVal intValue As Integer) As Integer '基类的可被派生类重写的方法
            GetY = Me.x * intValue
        End Function
        Protected Overrides Sub finalize() '基类的析构函数
            Console.WriteLine("(8)、基类的析构函数 Finalize 被调用")
            MyBase.Finalize()
        End Sub

        Public Sub vbCrLfA()  '基类的公共方法
            Console.WriteLine(vbCrLf)
        End Sub
    End Class
End Module

这就是基类,要想一个类具有基类的特性,那就必须具有可被重写或可被重载的函数或方法,最好有 Protected 关键字命名的字段、属性方法,因为它标志着只有派生类可访问。有了这些条件,那此类才称得上可作为基类被继承。

下面我们来写一个由上面的类派生出来的另一个类:

Private Class derivedClass
        Inherits baseClass
        Public x As Single = 100.6273
        Public Sub New()
            MyBase.New() 'MyBase关键字表示引用当前类的基类的指定方法,这里为基类的New构造函数
            Console.WriteLine("(2)、派生类的 New 构造函数被调用,引用了基类的构造函数")
        End Sub
        Protected Overrides Sub Finalize()
            Console.WriteLine("(7)、派生类的析构函数 Finalize 被调用")
            MyBase.finalize() '这里使用基类的析构函数类执行清理任务
        End Sub
        Public Overrides Function GetY(intValue As Integer) As Integer

            '这里重写了基类中 GetY 方法,但却不是用基类此方法的原始计算方法,而是进行了扩展和修改与完善
            For i = 0 To intValue
                Me.y += MyBase.GetY(i)  '用基类的GetY方法获取到的Y值来进行累加的结果,基类GetY方法的参数为循环值
            Next
            Return Me.y   '基类中用 protected 声明的 y 字段可以在派生类中使用
        End Function
        Public Sub intValue() '派生类的公共方法,对派生类中的X字段值取整
            Int(x)  '取整
        End Sub
    End Class

我们通过声明 Inherits 关键字,来标识该类的基类是谁,如果没有标识的类,比如 BaseHenry,VB.Net就会视其为派生自Object基类,这是种隐式继承,和结构是隐式继承自 ValueType 类的方式是一样的。

那这些overrides与 overload标识是什么意思呢?

我们使用继承,就要允许派生类中的某些属性或方法有与基类不同的行为,可以让派生类重写基类的方法或函数。但基类也得要同意你才能重写 才行啊,否则不就会发生命名冲突了吗?

因为派生类的对象是可以使用基类的公用成员的,那怎么知道哪些基类的方法与属性是被派生类重写了呢?所以就必须有一个约定:我们在基类中用 Overridable 修饰符来标识允许基类中的属性或方法在其派生类中可以被重写,没有标识的其实就是默认为有 NotOverridable 修饰符来隐式地标识,用于提醒编译器该属性或方法不可被重写;然后在派生类重写时,我们就用 Overrides 修饰符来标识哪些是重写自基类中定义的 Overridable 属性或方法 。

现在我们,调用派生类和基类的函数、字段和方法,来看看结果:

Sub Main()
        Dim myValue As New derivedClass
        myValue.GetY(5) '调用派生类的 GetY 函数 
        Console.WriteLine("(3)、调用派生类的 GetY 函数计算后返回 y 的值为:{0} ", myValue.GetY(5))
        Dim x As Single = myValue.x '读取派生类中的公共字段变量的值
        Console.WriteLine("(4)、调用派生类中 x 字段的值为:{0} ", x)
        myValue.intValue()  '调用派生类的公共方法
        Dim b As Integer = myValue.x
        Console.WriteLine("(5)、调用派生类的 intValue方法后派生类中 x 字段的值为:{0} ", b)
        myValue.vbCrLfA()  '调用基类的公共方法,因为 derivedClass 是 baseClass 类派生出的,所以可继承基类的所以公共成员
        Console.WriteLine("(6)、调用基类的 vbCrLfA 公共方法进行换行,因为派生类可继承基类的所以公共成员")
        Console.Read()
    End Sub

结果如图:

注意:Finalize 方法只有当程序结束后才会被触发。
大家会奇怪,只在 Main 中实例化了一个派生类的对象,为什么先会出现执行“基类的构造”?

其实是派生类 derivedClass 中的这段代码在作怪:

Public Sub New()
      MyBase.New()    'MyBase关键字表示引用当前类的基类的指定方法,这里为基类的New构造函数
      Console.WriteLine("(2)、派生类的 New 构造函数被调用,引用了基类的 New 构造函数")
End Sub

我们必须要注意这一点,就是派生类的构造函数与析构函数都必须重新编写。New 构造函数一般用于打开文件、连接到数据库 、初始化变量以及处理任何需要在可使用对象前完成的其他任务。我们必须在 Sub New 构造函数中的第一行代码使用语句 MyBase.New(),来调用该类的基类的构造函数,以获得基类的性质。析构函数则是在 Sub Finalize 中执行完对派生类的的清理任务,如保存状态信息、关闭文件和与数据库的连接,以及执行在 释放对象前必须完成的其他任务之后,在析构函数的最后一句使用语句 MyBase.Finalize() 显式调用其基类的 Sub Finalize 方法,以析构MyBase.New ()构造的内容。所以你从程序运行结果中也可以很清楚的看出这一顺序。

讲到类的继承,我们还得明白 重载 与 隐藏 的问题。

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Visual Studio 2003下开发网站的都知道ASP.NET 1.1网站生成后都是一个唯一命名的程序集(项目名称.DLL),但是这种情况在Visual Studio 2005的网站开发中不见了。Visual Studio 2005给我们提供了“发布网站”这样方便的功能,不用在像以前一样COPY的部署,但是采用其“发布网站”的功能,会在站点的BIN目录中产生App_Code.compiled,App_Code.dll,App_Web_xxxxxx.dll,项目名称.dll等等这样的程序集,如果不采用预编译的方式那么产生的文件会更加的多,因为很多都是随机命名也没有什么规律可言;这样会给那些想COPY更新的人带来不便,因为原来的文件不能被覆盖,需要先删除再COPY;有很多时候可能就是更新了后台代码,直接生成项目或是WEB的程序集,像以前一样直接覆盖DLL的方式也很简单。 传统的生成或是发布网站的方式没有任何问题,当使用Web Deployment Projects工具生成唯一程序集时出现了错误信息“Aspnet_merge.exe Exited with Code 1”(Aspnet_merge.exe 退出,错误代码1),这样的信息根本无法让我们办断到底是哪里出了问题。好,下面依次打开VS 2005的工具-选项-项目和解决方案-生成并运行,设置“MSBuild 项目生成输出详细信息”,选择“详细”。再次生成Web Deployment Projects项目,注意“输出”框内的信息现在变得非常丰富了,最后导致无法编译的问题终于出来了“An error occurred when merging assemblies: ILMerge.Merge: ERROR!!: Duplicate type ‘_Default’ found in assembly 'App_Web_k5hhsnh0'”,它的意思是说在程序集中发现了相同的型_Default,经过我检查确实在我们的WEB项目中存在了两个_Default(在不同的目录中),这样的问题通过一般的生成完成和发布网站肯定都是检测不出来的,运行也是正常的。VS 2005的WEB项目默认的把命名空间给去掉了,可以手动增加一个命名空间,cs代码中加入namespace的语句块,另外别忘了在aspx文件的<@page>的Inherits中写入对应的[namespace].[名];经过这样的操作再次编译成一个程序集就没有问题了。或者直接把aspx页面的Inherits改成“路径_文件名”,cs文件的名也改成同样的名称;可是如果一个网站有很多的目录,很多的文件,而且又有多个客户版本,那修改起来就非常的麻烦,为此特意开发了该工具,大大提高了工作效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值