类 的继承性(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 ()构造的内容。所以你从程序运行结果中也可以很清楚的看出这一顺序。
讲到类的继承,我们还得明白 重载 与 隐藏 的问题。
类 的继承性(Inherits)与 重写(Overrides)的更多相关文章
- JAVASE(九)面向对象特性之 : 继承性、方法重写、关键字super、
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 1.继承性 1.1 为什么要类的继承性?(继承性的好处) ①减少了代码的冗余,提高了代码的复用性:②更好 ...
- Java类的设计----方法的重写、覆盖
方法的重写.覆盖 在子类中可以根据需要对从父类中继承来的方法进行改造—覆盖方法(方法的重置.重写),在程序执行时,子类的方法将覆盖父类的方法. 覆盖方法必须和被覆盖方法具有相同的方法名称.参数列表和返 ...
- swift新建类和子类方法的重写与重载
1.首先什么是重写与重载? 一.重写(override) override是重写(覆盖)了一个方法,以实现不同的功能.一般是用于子类在继承父类时,重写(重新实现)父类中的方法. 重写(覆盖)的规则: ...
- Python_类的继承与方法重写
1.新建子类时,括号内要传入继承的父类名 2.super()方法:自动寻找当前类的父类,并调用父类的构造函数,初始化属性值 class Cup: #构造函数,初始化属性值 def __init__(s ...
- Java Object类中toString方法的重写
Object类中的tostring方法的: 当我们输出一个对象时,实际是输出的是这个类中的tostring方法,是一个地址值,而不是类中的属性. 1 一:子类没有重写Object类中的toStrinn ...
- 两个类似的ViewModel一个可以重写事件,另一个不能重写事件,是哪里出了错。
答:继承错了,BaseViewModel里面是事件.
- 【转载】 C++多继承中重写不同基类中相同原型的虚函数
本篇随笔为转载,原文地址:C++多继承中重写不同基类中相同原型的虚函数. 在C++多继承体系当中,在派生类中可以重写不同基类中的虚函数.下面就是一个例子: class CBaseA { public: ...
- android开发之重写Application类
在android应用开发中,重写Application也算是比较常见的,以前开发的一些程序太过于简单,都不要重写这个类,但是在真正的商业开发中,重写Application类几乎是必做的. 为什么要重写 ...
- Android_ 重写系统Crash处理类,保存Crash信息到SD卡 和 完美退出程序的方法
转载时注明地址:http://blog.csdn.net/xiaanming/article/details/9344703 我们开发Android应用的时候,当出现Crash的时候,系统弹出一个警告 ...
随机推荐
- pca图像识别
代码下载:基于PCA(主成分分析)的人脸识别 人脸识别是一个有监督学习过程,首先利用训练集构造一个人脸模型,然后将测试集与训练集进行匹配,找到与之对应的训练集头像.最容易的方式是直接利用欧式距离计算测 ...
- iOS 面试题汇总
1. Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么? 答: Object-c的类不可以多重继承;可以实现多个接口,通过实现 ...
- 南阳oj-喷水装置(一)
喷水装置(一) 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 现有一块草坪,长为20米,宽为2米,要在横中心线上放置半径为Ri的喷水装置,每个喷水装置的效果都会让以 ...
- (原)ubuntu16中编译boost1.61.0库
转载请注明出处: http://www.cnblogs.com/darkknightzh/p/5797940.html 参考网址: http://www.boost.org/doc/libs/1_61 ...
- vs2010中出现:程序管理器匹配不正确错误
http://bbs.csdn.net/topics/360074795 这是一篇csdn上的讨论帖,第15楼给出了正解
- LInux系统的C语言开发工具笔记
常用的C语言开发工具有很多,每个开发工具所支持的库函数和对标准的实现都有差异.对于初学者,选择一款使用广泛.上手容易的开发工具才是王道.在Windows 上很多从事C和C++开发的人员都选择VS作为开 ...
- AJAX Data 传值 无效的JSON基元:AJAX jQuery的方法,用c#WEBMETHOD-c#,jquery.
我有这样的代码:I数据值,而不是连接字符串作为对象常量.为什么?看到这里 我的代码是这样的:- $.ajax({ url: "../Member/Home.aspx/SaveClient&q ...
- WPF 利用子线程弹出子窗体的研究
一般来说子线程都是用来处理数据的,主窗体用来实现展现,但是有些时候我们希望子窗体实现等待效果,遮挡主窗体并使主窗体逻辑正常进行,这个业务需求虽然不多,但是正好我们用到了,于是我打算把研究成果写在这了. ...
- 如何不保存Word即可用Word打开想显示的内容!
今天遇到客户需要将数据用Word预览,原来做的时候是保存到本地然后打开,客户说这样不好,因为不一定预览了一定要保存,于是我翻箱倒柜的发现真没资料啊!!幸好经过我的大量实验(好吧,我是挨个方法试的!), ...
- 定时任务:Java中Timer和TimerTask的使用
java.util.Timer定时器,实际上是个线程,定时调度所拥有的TimerTasks. 一个TimerTask实际上就是一个拥有run方法的类,需要定时执行的代码放到run方法体内,TimerT ...