VB.Net中文教程(3) 继承与封装性

封装|继承|教程|中文

1. 继承与封装性(Encapsulation)
1.1 公用与私有数据

前面已介绍「封藏性」(Encapsulation) 之观念。即是﹕类别内所定义之资料成员﹐只限于程序成员才能存取之。现在所面临之问题为﹕子类别能否直接存取父类别之资料呢﹖就如同﹕儿女从父母亲继承了财产﹐但能否取用或卖掉继承而来的财产呢﹖如果可以﹐显然违背了「封藏性」之理想。如果不行﹐显然带给程序员莫大之限制。理论上﹐百分之百的封藏性最为完美﹔但应用上﹐若给予子类别若干优待﹐能提高程序之弹性及效率。为了解决此鱼与熊掌不可兼得之困境﹐VB提供三种选择﹕

(1) Public ──指定某些数据为公用的﹐任何程序皆可直接取用之﹔此时并无任何封藏作用。
(2) Protected ──指定某些资料为家族公用﹐亦即只有子孙类别内之程序可取用﹐非子孙类别之程序必须呼叫家族内之程序代为存取。
(3) Private ──指定某资料为类别私有﹐只限于该类别之程序才可取用。子类别之程序也必须呼叫父类别之程序代为存取﹐此时具百分之百封藏性。

先前介绍「封装性」基本概念时,您已经认识了Public和Private的用意了,至于Protected则配合继承来使用,于是在此特别强调它。
由于VB向现实妥协﹐开了方便之门﹐无百分之百封藏性﹔所以有些人认为 VB并非完美的 OOP语言。您认为如何呢﹖请看个程序﹕

'ex01.bas
Imports System.ComponentModel
Imports System.Drawing
Imports System.WinForms
'---------------------------------------------------------
Class Person
Private name As String
Public age As Integer
Public Sub New(ByVal na As String, ByVal a As Integer)
name = na
age = a
End Sub
End Class

Class Teacher
Inherits Person

Public salary As Single
Public Sub New(ByVal na As String, ByVal a As Integer, ByVal sa As Single)
MyBase.New(na, a)
salary = sa
End Sub
Public Sub modifyAge(ByVal a As Integer)
age = a
End Sub
End Class
'--------------------------------------------------------
Public Class Form1
Inherits System.WinForms.Form

Public Sub New()
MyBase.New()
Form1 = Me
'This call is required by the Win Form Designer.
InitializeComponent()
'TODO: Add any initialization after the InitializeComponent() call
End Sub
'Form overrides dispose to clean up the component list.
Public Overrides Sub Dispose()
MyBase.Dispose()
components.Dispose()
End Sub

#Region " Windows Form Designer generated code "
.......
#End Region

Protected Sub Form1_Click( ByVal sender As Object,
ByVal e As System.EventArgs)
Dim crag As New Teacher("Crag", 38, 45000)
crag.modifyAge(42)
MessageBox.Show( "AGE: " + str(crag.age) + ", SALARY: "
+ str(crag.salary))
End Sub
End Class

此程序输出如下﹕
AGE: 42 SALARY: 45000

Person之age资料成员定义为 Public﹐表示 age为公用数据﹐任何程序皆可存取之。因之﹐Teacher 之 modifyAge()可使用age这名称。相对地﹐于 Teacher类别中﹐就不得使用name这名称﹐因为name定义为Privatec﹐表示name为Person类别之私有资料。再看Teacher类别之salary资料﹐它定义为Public﹐表示公用之意。所以Form1_Click()可直接使用 crag.salary格式取得salary之值。然而﹐不能写成﹕crag.name ﹐因为name为私有资料。例如,下述程序是不对的:

'ex02.bas
'Some Error Here!
Imports System.ComponentModel
Imports System.Drawing
Imports System.WinForms
'---------------------------------------------------------
Class Person
Private name As String
Public age As Integer
Public Sub New(ByVal na As String, ByVal a As Integer)
name = na
age = a
End Sub
End Class

Class Teacher
Inherits Person

Public salary As Single
Public Sub New(ByVal na As String, ByVal a As Integer, ByVal sa As Single)
MyBase.New(na, a)
salary = sa
End Sub
Public Sub modifyName(ByVal na As String)
name = na 'Error Here!
End Sub
End Class
'--------------------------------------------------------
Public Class Form1
Inherits System.WinForms.Form

Public Sub New()
MyBase.New()
Form1 = Me
'This call is required by the Win Form Designer.
InitializeComponent()
'TODO: Add any initialization after the InitializeComponent() call
End Sub
'Form overrides dispose to clean up the component list.
Public Overrides Sub Dispose()
MyBase.Dispose()
components.Dispose()
End Sub
#Region " Windows Form Designer generated code "
.......
#End Region
Protected Sub Form1_Click( ByVal sender As Object,
ByVal e As System.EventArgs)
Dim crag As New Teacher("Crag", 38, 45000)
crag.modifyName("Crag Clinton")
MessageBox.Show( "AGE: " + str(crag.age) + ", SALARY: "
+ str(crag.salary))
End Sub
End Class

因为name是Person类别的私有资料,在子类别Teacher的modifyName()里不能使用此资料名称,所以错了。如果将Person类别定义为﹕

'ex03.bas
Imports System.ComponentModel
Imports System.Drawing
Imports System.WinForms
'---------------------------------------------------------
Class Person
Protected name As String
Public age As Integer

Public Sub New(ByVal na As String, ByVal a As Integer)
name = na
age = a
End Sub
Public Function GetName() As String
GetName = name
End Function
End Class

Class Teacher
Inherits Person

Public salary As Single
Public Sub New(ByVal na As String, ByVal a As Integer, ByVal sa As Single)
MyBase.New(na, a)
salary = sa
End Sub
Public Sub modifyName(ByVal na As String)
name = na
End Sub
End Class
'--------------------------------------------------------
Public Class Form1
Inherits System.WinForms.Form

Public Sub New()
MyBase.New()
Form1 = Me
'This call is required by the Win Form Designer.
InitializeComponent()
'TODO: Add any initialization after the InitializeComponent() call
End Sub
'Form overrides dispose to clean up the component list.
Public Overrides Sub Dispose()
MyBase.Dispose()
components.Dispose()
End Sub
#Region " Windows Form Designer generated code "
......
#End Region
Protected Sub Form1_Click( ByVal sender As Object,
ByVal e As System.EventArgs)
Dim crag As New Teacher("Crag", 38, 45000)
crag.modifyName("Crag Clinton")
MessageBox.Show( "AGE: " + str(crag.age) + ", NAME: "
+ crag.GetName())
End Sub
End Class

此程序输出:
AGE: 42, NAME: Crag Clinton

此时﹐name为家族公用之资料﹐凡是Person之子孙类别皆可取用之。但家族外之程序(如 Form1_Click()程序)仍不得直接使用之。如果上述定义改为﹕

Class Person
Protected name As String
Private salary As Decimal
Public age As Integer

Public Sub New(ByVal na As String, ByVal a As Integer)
name = na
age = a
End Sub
End Class

此时﹐salary为类别私有﹐其它类别不得使用。name为家族私有﹐家族外之类别不得使用。age为公用﹐任何类别皆可用。

1.2 公用与私有程序
上节介绍过﹕资料成员有 Private、Protected 及Public之分。同样地﹐程序成员也可分为 Private、Protected 及Public。虽然在应用上﹐程序成员大多定义为Public﹐但必要时﹐也能将过程定义为Private 或 Protected。私有程序和私有资料一样﹐只限于该类别之程序才能呼叫它。例如﹕

'ex04.bas
Imports System.ComponentModel
Imports System.Drawing
Imports System.WinForms
'----------------------------------------------------------------------
Class Person
Private name As String
Private age As Integer
Private Sub modifyAge(ByVal a As Integer)
age = a
End Sub
Public Sub New(ByVal na As String, ByVal a As Integer)
name = na
age = a
End Sub
Public Sub modify(ByVal na As String, ByVal a As Integer)
name = na
modifyAge(a)
End Sub
Public Sub Show()
Messagebox.Show("Name: " + name + " Age: " + str(age))
End Sub
End Class
'-------------------------------------------------------------------
Public Class Form1
Inherits System.WinForms.Form

Public Sub New()
MyBase.New()

Form1 = Me
'This call is required by the Win Form Designer.
InitializeComponent()
'TODO: Add any initialization after the InitializeComponent() call
End Sub
'Form overrides dispose to clean up the component list.
Public Overrides Sub Dispose()
MyBase.Dispose()
components.Dispose()
End Sub
#Region " Windows Form Designer generated code "
.......
#End Region
Protected Sub Form1_Click( ByVal sender As Object,
ByVal e As System.EventArgs)
Dim p1 As New Person("David", 25)
p1.Show()
p1.modify("David Smith", 28)
p1.Show()
End Sub
End Class

此程序输出:
Name: David Age: 25
Name: David Smith Age: 45

modifyAge()为私有程序﹐New()及modify()为公用程序。modifyAge()为Person类别之程序成员﹐所以modify()能呼叫modifyAge()。Person类别外之函数不能呼叫modifyAge()。例如﹕在Form1_Click()中﹐可写着 p1.modify()﹐因为modify()为公用程序。但于Form1_Click()内﹐就不可写着 p1.modifyAge()﹐因为modifyAge()为 Private函数。如果放宽对modifyAge()之限制﹐使Person之子类别能呼叫modifyAge()﹐就须定义modifyAge()为 Protected函数﹐如下﹕

'ex05.bas
Imports System.ComponentModel
Imports System.Drawing
Imports System.WinForms
'----------------------------------------------------------------------
Class Person
Protected name As String
Private age As Integer
Protected Sub modifyAge(ByVal a As Integer)
age = a
End Sub
Public Sub New(ByVal na As String, ByVal a As Integer)
name = na
age = a
End Sub
Public Sub Show()
Messagebox.Show("Name: " + name + " Age: " + str(age))
End Sub
End Class

Class Teacher
Inherits Person

Public Sub New(ByVal na As String, ByVal a As Integer)
MyBase.New(na, a)
End Sub
Public Sub modify(ByVal na As String, ByVal a As Integer)
MyBase.name = na
MyBase.modifyAge(a)
End Sub
End Class
'-------------------------------------------------------------------
Public Class Form1
Inherits System.WinForms.Form

Public Sub New()
MyBase.New()
Form1 = Me
'This call is required by the Win Form Designer.
InitializeComponent()
'TODO: Add any initialization after the InitializeComponent() call
End Sub
'Form overrides dispose to clean up the component list.
Public Overrides Sub Dispose()
MyBase.Dispose()
components.Dispose()
End Sub
#Region " Windows Form Designer generated code "
......
#End Region
Protected Sub Form1_Click( ByVal sender As Object,
ByVal e As System.EventArgs)
Dim p1 As New Teacher("David", 25)
p1.Show()
p1.modify("Kent Smith", 45)
p1.Show()
End Sub
End Class

此程序输出:
Name: David Age: 25
Name: Kent Smith Age: 45

此时﹐子孙类别之函数能呼叫modifyAge()﹐但家族外之类别仍不可呼叫它。总结归纳为简单规则﹕
◎如果允许任何类别使用﹐就宣告为Public。
◎如果允许子类别使用﹐就宣告为Protected 。
◎如果允许本类别使用﹐就宣告为Private 。
请在看个例子:

'ex06.bas
Imports System.ComponentModel
Imports System.Drawing
Imports System.WinForms
'----------------------------------------------------------------------
Class Person
Protected name As String
Private age As Integer
Protected Sub modifyAge(ByVal a As Integer)
age = a
End Sub
Public Sub New(ByVal na As String, ByVal a As Integer)
name = na
age = a
End Sub
Public Sub Show()
Messagebox.Show("Name: " + name + " Age: " + str(age))
End Sub
End Class

Class Teacher
Inherits Person

Public Sub New(ByVal na As String, ByVal a As Integer)
MyBase.New(na, a)
End Sub
Protected Sub modify(ByVal na As String, ByVal a As Integer)
MyBase.name = na
MyBase.modifyAge(a)
End Sub
End Class

Class FullTime_Teacher
Inherits Teacher

Public Sub New(ByVal na As String, ByVal a As Integer)
MyBase.New(na, a)
End Sub
Public Sub modifyValue(ByVal na As String, ByVal a As Integer)
MyBase.modify(na, a)
End Sub
Public Sub modifyData(ByVal na As String, ByVal a As Integer)
MyBase.name = na
MyBase.modifyAge(a)
End Sub
End Class
'-------------------------------------------------------------------
Public Class Form1
Inherits System.WinForms.Form

Public Sub New()
MyBase.New()
Form1 = Me
'This call is required by the Win Form Designer.
InitializeComponent()
'TODO: Add any initialization after the InitializeComponent() call
End Sub
'Form overrides dispose to clean up the component list.
Public Overrides Sub Dispose()
MyBase.Dispose()
components.Dispose()
End Sub
#Region " Windows Form Designer generated code "
.......
#End Region
Protected Sub Form1_Click( ByVal sender As Object,
ByVal e As System.EventArgs)
Dim p1 As New FullTime_Teacher("David", 25)
p1.Show()
p1.modifyValue("Kent Smith", 45)
p1.Show()
End Sub
End Class

此程序输出:
Name: David Age: 25
Name: Kent Smith Age: 45

Show()是Person类别的Public程序,孙子类别FullTime_Teacher继承之,成为FullTime_Teacher类别的Public程序,所以Form1_Click()程序能写着指令:p1.Show()。name和modifyAge()是Person的Protected成员,Teacher的modify()程序里能直接使用它们。而且FullTime_Teacher的modifyData()程序里能直接使用它们。但是Form1_Click()就无法使用它们。modify()是Teacher的Protected成员,FullTime_Teacher的modifyValue()程序里能直接使用它们,但Form1_Click()就不行使用。所以若将上述Form1_Click()的指令改为如下,就不对了:

Protected Sub Form1_Click( ..... )
Dim p1 As New FullTime_Teacher("David", 25)
p1.Show()
p1.modify("Kent Smith", 45) 'Error!
p1.modifyAge(24) 'Error!
p1.Show()
End SubEnd Class
n

时间: 2024-09-04 10:02:40

VB.Net中文教程(3) 继承与封装性的相关文章

VB.Net中文教程(1) 类别与封装性

封装|教程|中文 1. 类别的「程序成员」(Procedure Member) 类别 (Class)之任务是把资料(Data)和程序(Procedure)组织并封装起来.类别告诉计算机﹕「其对象应含有那些资料.应含有那些程序裨处理外界传来之讯息」.类别须详细说明它的资料及程序﹐我们称此资料是类别之「资料成员」(Data Member) ﹔而称此程序是类别之「程序成员」(Procedure Member).有关类别内容之叙述﹐就是所谓的类别定义(Class Definition).类别定义之格式为

VB.Net中文教程(4) 类别继承(Inheritance)关系

继承|教程|中文 1. 类别之继承 类别之间﹐有些互为独立﹐有些具有密切关系.兹介绍类别间常见的关系──「父子」关系﹔由于儿女常继承父母之生理或心理特征﹐所以又称此关系为「继承」(Inheritance) 关系.类别间之密切关系﹐把相关的类别组织起来﹐并且组织程序内之对象.若程序内之对象毫无组织﹔呈现一片散沙﹐就不是好程序.完美之VB程序﹐必须重视类别间之关系﹐对象是有组织的. 如果 A类别「继承」 B类别﹐则称 A为「子类别」(Subclass)﹐也称B 为「父类别」(Superclass)﹐

VB.Net中文教程(2) Composite样式

教程|中文 1. 从Whole-part关系谈起 回想传统的软件师﹐常甚专注于撰写程序(procedure) 来处理某些资料(data)﹐较少关心软件的整体结构(architecture).在现在的OO软件中﹐把资料及其相关的程序结合在一起﹐封装(encapsulate) 在对象之中.软件师在使用对象时﹐通常把对象视为黑箱(black-box) ﹐不会关心于对象内部之细节﹔因之能专注于对象之间的关系.软件师的主要工作﹐就是在于建立对象之间的互助合作(collaboration) 关系﹐为对象安排

VB.Net中文教程(11) Prototype样式

教程|中文 主题: Prototype样式副题: 多形性.接口(Interface) ????????? 内容 ?????????v 1. 样式v 2. 对象之原型(object prototype)v 3. 以VB落实Prototype样式v 4. Prototype样式之应用----- 组件之设计与组装 1. 样式 Erich Gamma 等人的名著──"Design Patterns: Elements of Reusable Object-Oriented Software"

VB.Net中文教程(8) 对象(Object)基本概念

object|对象|概念|教程|中文 主题: 对象(Object)基本概念 ???????????? 内容 ????????????v 1. 何谓「对象导向」? v 2. 认识与寻找对象v 3. 对象之分类与组织v 4. 类别之设计 v 5. 对象之行为v 6. 讯息与运算v 7. 类别之定义 v 8. 着手写 VB程序 大地运转.花开花谢.及枫叶飘零 ...... 是自然界对象之行为.对象行为交互作用﹐造成多采多姿的大自然.软件的对象是自然界对象的抽象表示,软件就逼真地表达自然界的实际景象﹐于

VB.Net中文教程(12) 共享成员(Shared Member)

教程|中文 主题: 共享成员(Shared Member) ?????? 内容 ??????v 1. 共享资料成员v 2. 共享程序成员 您已经习惯像 New Employee("Tom", 25)这样的指令了,看到这个指令可以想向它是:Employee.New("Tom", 25),于是不难想象到,原来类别也是对象!这个类别对象(Class Object)接到New()讯息时,就去诞生一个对象,原来类别对象就是妈妈对象(Meta Object)!妈妈是小孩共有的,

VB.Net中文教程(13) Whole-Part关系

教程|中文 主题: Whole-Part关系 ?????????? 内容 ??????????v 1. 对象Whole-Part关系v 2. 组合/部分关系v 3. 包含者/内容关系v 4. 集合/成员关系 1. 对象Whole-Part关系 类别继承(Class inheritance)和对象组合(Object composition)是软件再使用(Reuse)的两大法宝.类别继承就是建立父.子类别之关系﹔例如﹐「学生」可分为「大学生」.「中学生」和「小学生」三类别﹐其继承关系图标如下﹕ 图1

VB.Net中文教程(5)程序多重定义

程序|教程|中文 1. 程序成员的多重定义 「程序多重定义」(Function Overloading)又称为「程序重复定义」.它让对象更具弹性﹐能处理多样化之讯息.这观念源于日常生活经验.例如﹐我们常说﹕ ◎ 猫 玩 绣球 ◎ 猫 玩 老鼠 ◎ 猫 玩 鱼 猫玩绣球与玩老鼠之玩法不尽相同.但何以使用同一动词──「玩」呢﹖也许人们认为其目的是一致的﹕猫获得快乐.上述的「猫」为类别﹐而某只猫是对象.例如﹕加菲猫是对象﹐它可接受讯息── 其中﹐「玩」代表着动作和过程﹐而绣球.老鼠及鱼则是「玩」之对象

VB.Net中文教程(6) 母子对象关系

对象|教程|中文 1. 特殊Whole-Part关系 ---- 母子对象关系 大家已经熟悉父子类别关系﹐也就是「继承」关系了.于此说明另一种常见关系── 母子对象.一般称之为「组合/部分」关系.日常生活中﹐处处可见到这种母子对象.例如﹐客厅内有沙发.桌子.椅子等等.客厅是母对象﹐沙发.桌子.椅子是子对象.再如计算机屏幕上的窗口内有按钮.选择表.对话盒等等.窗口是母对象﹐按钮.选择表是子对象.于此将说明如何建立母子对象关系.有了关系﹐母子就能互相沟通了.母子对象之间﹐如何沟通呢﹖也就是说﹐母对象如