子类可以访问其基类中的事件,但子类中的代码不能引发该事件。可以在基类中实现一个Protected方法,允许任何派生类引发该方法。
基类
Public Class Person
Private mName As String
Private mBirthDate As Date
Private mID As String
Public Event NameChanged(ByVal newName As String)
'供子类引用
Protected Sub OnNameChanged(ByVal newName As String)
RaiseEvent NameChanged(newName)
End Sub
Public Event DataChanged(ByVal field As String, ByVal newValue As Object)
Protected Sub OnDataChanged(ByVal field As String, ByVal newValue As Object)
RaiseEvent DataChanged(field, newValue)
End Sub
'可重写的方法
Public Overridable Property Name() As String
Get
Return mName
End Get
Set(ByVal value As String)
mName = value
'改名事件
RaiseEvent NameChanged(mName)
End Set
End Property
'可重写的方法
Public Overridable Property BirthDate() As Date
Get
Return mBirthDate
End Get
Set(ByVal value As Date)
mBirthDate = value
RaiseEvent DataChanged("BirthData", value)
End Set
End Property
'用于继承
Protected Property Identity As String
Get
Return mID
End Get
Set(ByVal value As String)
mID = value
End Set
End Property
'这里是一个有意的错误,年龄是一个负数.用来测试Shadows
Public ReadOnly Property age() As Integer
Get
Return CInt(DateDiff(DateInterval.Year, Now, BirthDate))
End Get
End Property
Public Overrides Function ToString() As String
Return Me.Name
End Function
Public Sub New(ByVal name As String)
Me.Name = name
Debug.WriteLine("Person constructor")
End Sub
End Class
一层派生
Public Enum NameTypes
Informal = 1
Formal = 2
Normal = 3
End Enum
Public Class Employee
Inherits Person
'子类属性
Public Property HireDate As Date
Private Property mSalary As Double
'Private mName As String
'重写BirthDate
Public Overrides Property BirthDate() As Date
Get
Return MyBase.BirthDate
End Get
Set(ByVal value As Date)
If DateDiff(DateInterval.Year, value, Now) > 16 Then
MyBase.BirthDate = value
Else
'Throw New ArgumentException("An employee must be at least 16 years old.")
MsgBox("An employee must be at least 16 years old.")
End If
'OnDataChanged("BirthDate", value)
End Set
End Property
'重载基类Name属性
'Dictionary<TKey,TValue> 泛型类提供一组键到一组值的映射。 每次对字典的添加都包含一个值和与其关联的键。
'TKey,字典中的键的类型。
'TValue,字典中的值的类型。
Private mNames As Dictionary(Of NameTypes, String)
'Name属性是一个属性数组,允许在同一个属性中存储多个值.
Public Overloads Property Name(ByVal type As NameTypes) As String
Get
If mNames Is Nothing Then mNames = New Dictionary(Of NameTypes, String)
Return mNames(type)
End Get
Set(ByVal value As String)
If mNames Is Nothing Then mNames = New Dictionary(Of NameTypes, String)
If mNames.ContainsKey(type) Then
mNames.Item(type) = value
Else
mNames.Add(type, value)
End If
If type = NameTypes.Normal Then
MyBase.Name = value
End If
End Set
End Property
'用Overrides关键字来表明重写基类中的Name方法,使用Overloads关键字来表明在子类中重载这个方法。
Public Overloads Overrides Property Name() As String
Get
If mNames Is Nothing Then mNames = New Dictionary(Of NameTypes, String)
Return mNames(NameTypes.Normal)
End Get
Set(ByVal value As String)
If mNames Is Nothing Then
mNames = New Dictionary(Of NameTypes, String)
Else
mNames(NameTypes.Normal) = value
OnNameChanged(mNames(NameTypes.Normal))
End If
End Set
End Property
'遮蔽方法
Public Shadows Property age() As Integer
Get
Return CInt(DateDiff(DateInterval.Year, BirthDate, Now))
End Get
Set(ByVal value As Integer)
BirthDate = DateAdd(DateInterval.Year, -value, Now)
End Set
End Property
Public Property EmployeeNumber As Integer
Get
Return CInt(Identity)
End Get
Set(ByVal value As Integer)
Identity = CStr(value)
End Set
End Property
Public Property Salary() As Double
Get
Return mSalary
End Get
Set(ByVal value As Double)
mSalary = value
OnDataChanged("Salary", mSalary)
End Set
End Property
Sub New(ByVal name As String)
MyBase.new(name)
Debug.WriteLine("Employee constructor")
End Sub
End Class
二层派生
Public Class OfficeEmployee
Inherits Employee
Private mOffice As String
Public Property OfficeNumber() As String
Get
Return mOffice
End Get
Set(ByVal value As String)
mOffice = value
End Set
End Property
Public Overloads Property Name() As String
Get
Return MyBase.Name(NameTypes.Informal)
End Get
Set(ByVal value As String)
MyBase.Name = value
OnNameChanged(MyBase.Name)
End Set
End Property
'Public Shadows Property Name() As String
'Get
'Return MyBase.Name(NameTypes.Informal)
'End Get
'Set(ByVal value As String)
'MyBase.Name = value
'End Set
'End Property
Sub New(ByVal name As String)
MyBase.New(name)
Debug.WriteLine("OfficeEmployee constructor")
End Sub
End Class
客户端
客户端代码
Public Class Form1
Private Sub btnOk_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOk.Click
'1.这里把变量声明为Person类型,但是对象却是Employee类的—个实例。
'Dim person As Person
'person = New Employee()
'2.
'Dim person As Employee
'person = New Person
'3.,通过这个对象可以调用Employee类的任意方法,包括从Person类中继承来的方法.
'Dim person As OfficeEmployee = New OfficeEmployee("Mary")
'Dim person As Person = New Person("Mary")
Dim person As Employee = New Employee("Mary")
'Dim person As OfficeEmployee = New OfficeEmployee("Mary")
AddHandler person.NameChanged, AddressOf OnNameChanged
AddHandler person.DataChanged, AddressOf OnDataChanged
With person
.Name = "Fred"
.BirthDate = #11/1/2001#
'.age = 20
'.OfficeNumber = "A42"
'所以编译有错误, 不可以用子类方法
.Name(NameTypes.Formal) = "Mr.Frederick R.Jones,Sr."
.Name(NameTypes.Informal) = "Freddy"
.HireDate = #1/1/2020#
.Salary = 30000
txtName.Text = .ToString '.Name
txtBirthDate.Text = Format(.BirthDate, "Short date")
txtAge.Text = CStr(.age)
'txtOffice.Text = .OfficeNumber
'DisplayPerson(person)
txtFomal.Text = .Name(NameTypes.Formal)
txtInfomal.Text = .Name(NameTypes.Informal)
txtHireDate.Text = Format(.HireDate, "Short date")
txtSalary.Text = Format(.Salary, "$0.00")
End With
End Sub
'通用例程
'Private Sub DisplayPerson(ByVal thePerson As Person)
Private Sub DisplayPerson(ByVal thePerson As Employee)
'Private Sub DisplayPerson(ByVal thePerson As OfficeEmployee) 'age属性会用遮蔽方法
With thePerson
txtName.Text = .ToString '.Name
txtBirthDate.Text = Format(.BirthDate, "Short date")
txtAge.Text = CStr(.age)
'txtOffice.Text = .OfficeNumber
End With
End Sub
'处理改名事件
Private Sub OnNameChanged(ByVal newName As String)
MsgBox("New name:" & newName)
End Sub
'处理生日或薪水改变事件
Private Sub OnDataChanged(ByVal field As String, ByVal newValue As Object)
MsgBox(field & ":" & newValue)
End Sub
End Class