VB.Net中文教程(3) 繼承與封裝性 (轉)

gugu99發表於2008-05-19
VB.Net中文教程(3) 繼承與封裝性 (轉)[@more@]

請注意 ......
著作權所有人:物澤事業股份有限公司、
  MISOO技術顧問團隊、物件導向雜誌作者、等。
u本摘自 物件導向雜誌、精通物件觀念與技術等書籍著作。
u本檔案僅供您的參閱,請遵守著作權法,不得做其它商業用途。


  主題:  繼承與封裝性


??????????  內容  ??????????
v 1. 繼承與封藏性

 


1. 繼承與封裝性(Encapsulation)
1.1 公用與私有資料

  前面已介紹「封藏性」(Encapsulation) 之觀念。即是﹕類別內所定義之資料成員﹐只限於成員才能存取之。現在所面臨之問題為﹕子類別能否直接存取父類別之資料呢﹖就如同﹕兒女從父母親繼承了財產﹐但能否取用或賣掉繼承而來的財產呢﹖如果可以﹐顯然違背了「封藏性」之理想。如果不行﹐顯然帶給程式設計師莫大之限制。理論上﹐百分之百的封藏性最為完美﹔但應用上﹐若給予子類別若干優待﹐能提高程式之彈性及。為了解決此魚與熊掌不可兼得之困境﹐VB提供三種選擇﹕

  (1) Public  ──指定某些資料為公用的﹐任何程式皆可直接取用之﹔此時並無任何封藏作用。
  (2) Protected ──指定某些資料為家族公用﹐亦即只有子孫類別內之程式可取用﹐非子孫類別之程式必須呼叫家族內之程式代為存取。
  (3) Private  ──指定某資料為類別私有﹐只限於該類別之程式才可取用。子類別之程式也必須呼叫父類別之程式代為存取﹐此時具百分之百封藏性。

  先前介紹「封裝性」基本概念時,您已經認識了Public和Private的用意了,至於Protected則配合繼承來使用,於是在此特別強調它。
  由於VB向現實妥協﹐開了方便之門﹐無百分之百封藏性﹔所以有些人認為 VB並非完美的 語言。您認為如何呢﹖請看個程式﹕

'ex01.bas
Imports System.ComponentModel
Imports System.Drawing
Imports System.s
'---------------------------------------------------------
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 FoDesigner.
  InitializeComponent()
  'TODO: Add any initialization after the InitializeComponent() call
  End Sub
  'Form overrs dispose to clean up the component list.
  Public Overrides Sub Dispose()
  MyBase.Dispose()
  components.Dispose()
  End Sub
 
#Region " Form Designer generated code "
  .......
#End Region
 
  Protected Sub Form1_Click( ByVal sender As ,
  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

 


 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-1004281/,如需轉載,請註明出處,否則將追究法律責任。

相關文章