560 likes | 632 Views
第 16 章 物件導向程式設計. 16-1 物件導向的基礎 16-2 類別與物件 16-3 類別的繼承 16-4 抽象類別與介面 16-5 多形的實作 16-6 運算子過載. 16-1 物件導向的基礎. 16-1-1 物件的基本觀念 16-1-2 物件導向程式分析 16-1-3 物件導向程式語言. 16-1-1 物件的基本觀念 - 說明. 「物件」( Object )是物件導向技術的關鍵,以程式角度來說,物件是資料與相關程序與函數結合在一起的組合體,如下圖所示:. 16-1-1 物件的基本觀念 - 物件特性.
E N D
第16章 物件導向程式設計 • 16-1 物件導向的基礎 • 16-2 類別與物件 • 16-3 類別的繼承 • 16-4 抽象類別與介面 • 16-5 多形的實作 • 16-6 運算子過載
16-1 物件導向的基礎 • 16-1-1 物件的基本觀念 • 16-1-2 物件導向程式分析 • 16-1-3 物件導向程式語言
16-1-1 物件的基本觀念-說明 • 「物件」(Object)是物件導向技術的關鍵,以程式角度來說,物件是資料與相關程序與函數結合在一起的組合體,如下圖所示:
16-1-1 物件的基本觀念-物件特性 • 狀態(State):物件屬性目前的狀態值,屬性儲存的是物件狀態,可以簡單的是布林值變數,也可能是另一個物件,例如:車子的車型、排氣量、色彩和自排或手排等屬性。 • 行為(Behavior):行為是物件可見部分提供的服務,即可作什麼事,例如:車子可以發動、停車、加速和換擋等。 • 識別字(Identity):識別字是用來識別不同物件,每一個物件都擁有獨一無二的識別字。
16-1-2 物件導向程式分析 • 物件導向的程式分析是將原來專注於演算法的程序和函數分解,轉換成了解問題本質的物件,將整個軟體視為一個個定義完善的物件,整個程式是由物件組成,強調物件的重複使用,在建立好下一層的每一個物件後,由下而上組合成整個應用程式的物件,以便解決整個問題。
16-1-3 物件導向程式語言-說明 • 物件導向程式語言的精神是物件,但支援物件的程式語言並不一定是物件導向程式語言,它可能只是物件基礎程式語言,如下所示: • 物件基礎程式語言(Object-based Languages):提供資料抽象化和物件觀念。例如:VB 6,不過VB.NET和Visual Basic 2005是一種物件導向程式語言。 • 物件導向程式語言(Object-oriented Languages):支援封裝、繼承和多形觀念。
16-1-3 物件導向程式語言-封裝 封裝(Encapsulation) • 封裝是將資料和處理資料的程序與函數組合成物件。在Visual Basic 2005定義物件是使用「類別」(Class),它屬於一種抽象資料型態,換句話說,就是替程式語言定義新的資料型態。
16-1-3 物件導向程式語言-繼承 繼承(Inheritance) • 繼承是物件的再利用,當定義好一個類別後,其他類別就可以繼承此類別的資料和方法,新增或取代繼承物件的資料和方法。
16-1-3 物件導向程式語言-多形 多形(Polymorphism) • 多形屬於物件導向最複雜的特性,類別如果需要處理各種不同的資料型態,此時並不需要針對不同資料型態建立專屬類別,可以直接繼承基礎類別,繼承此類別建立同名方法來處理不同的資料型態,因為方法的名稱相同,只是程式碼不同,也稱為「同名異式」。
16-2 類別與物件 • 16-2-1 宣告類別與建立物件 • 16-2-2 方法的過載 • 16-2-3 類別的建構子 • 16-2-4 類別的靜態成員 • 16-2-5 部分類別
16-2 類別與物件 • Visual Basic類別是物件原型,或者說是物件的藍圖。類別宣告分為兩部分,如下: • 成員資料(Data Member):物件的資料部分或稱為「成員變數」(Member Variables)。Visual Basic可以使用宣告成Private變數配合宣告成Public的Property程序屬性來存取,或是直接宣告成Public的變數,稱為欄位(Fields)。 • 成員方法(Method Member):物件處理資料的程式與函數,也就是方法(Methods)。
16-2-1 宣告類別與建立物件-說明 • 在Visual Basic程式宣告的類別是物件的藍圖,可以建立物件。事實上,類別的主要目的是建立完善的軟體元件,以便提供其他程式來使用或擴充其功能。 • 不過,類別有些方法是屬於類別本身,並不需讓其他程式呼叫,有些則是類別的使用介面,此時可以使用存取修飾子來控制類別的哪些成員是可以讓其他程式存取,哪些不允許,以達成資訊隱藏的目的。
16-2-1 宣告類別與建立物件-類別宣告(語法) • 類別宣告是使用Class/End Class關鍵字,通常我們會將類別建立成獨立程式檔案,即在專案加入類別檔案來宣告類別。其格式如下所示: Public Class 類別名稱 [Public | Private]成員資料 [Public | Private]成員方法 End Class • 上述Public Class後是宣告的類別名稱,其中主要是使用Public和 Private存取修飾子來定義的成員。
16-2-1 宣告類別與建立物件-類別宣告(存取修飾子) • Private修飾子:類別成員只能在類別本身呼叫或存取。例如:本節MyTime類別的intHour、intMinute和intSecond欄位是宣告成Private,只能讓屬性程序來存取。 • Public修飾子:類別成員沒有存取限制,它是此類別建立物件的對外使用介面,可以讓其他程式碼呼叫其成員方法或存取成員資料。例如:本節MyTime類別的SetTime()和GetTime()方法是宣告成Public。
16-2-1 宣告類別與建立物件-類別宣告(範例) • 例如:在Class1.vb類別檔案宣告處理時間資料的MyTime類別,如下所示: Public Class MyTime ……… End Class • 上述程式碼宣告名為MyTime類別。其中就是使用存取修飾子來宣告成員資料的屬性或欄位,或是成員方法的程序或函數。
16-2-1 宣告類別與建立物件-物件屬性的宣告(說明) • Visual Basic屬性比直接宣告成Public變數的欄位擁有更多控制能力,例如:加上程式碼來檢查資料範圍等。 • 屬性可以存取宣告成Private的變數,它是隱藏在類別的資訊。
16-2-1 宣告類別與建立物件-物件屬性的宣告(範例) Public Class MyTime Private intHour As Integer Private intMinute As Integer Private intSecond As Integer Property Hour() As Integer Get Return intHour End Get Set(ByVal Value As Integer) intHour = Value End Set End Property ……… End Class
16-2-1 宣告類別與建立物件-物件屬性的宣告(範例說明) • 在Property程序擁有Get和Set程序,如下所示: • Get程序:取得欄位值,以此例是傳回intHour變數值。 • Set程序:指定欄位值,程式碼使用指定敘述將欄位值指定成參數Value的值。
16-2-1 宣告類別與建立物件-物件屬性的宣告(唯讀屬性) • 如果是唯讀屬性,就需要使用ReadOnly修飾子,如下所示: ReadOnly Property Hour() As Integer Get Return intHour End Get End Property • 上述程式碼宣告唯讀屬性Hour,所以只有Get程序,而沒有Set程序。
16-2-1 宣告類別與建立物件-物件方法的宣告(程序或函數) Public Class MyTime ……… Public Function GetTime() As String Dim str As String str=intHour & ":" & intMinute &":"& intSecond Return str End Function Public Sub SetTime(ByVal h As Integer, _ ByVal m As Integer, ByVal s As Integer) intHour = h intMinute = m intSecond = s End Sub End Class
16-2-1 宣告類別與建立物件-建立物件 • 在Visual Basic建立物件是使用New關鍵字,可以依照類別藍圖來建立物件,傳回指向此物件的參考(因為物件是一種參考型態),如下所示: Dim now, open As MyTime now = New MyTime() open = New MyTime() • 上述程式碼在宣告MyTime類別的物件變數now和open後,使用New關鍵字建立物件,因為同一個類別可以建立多個物件,此時每一個物件稱為類別的「實例」(Instances)。
16-2-1 宣告類別與建立物件-存取物件屬性和方法(屬性) • 在建立物件後,就可以存取物件屬性與方法,其語法如下所示: 物件.屬性 物件.方法 • 屬性和方法是使用“.”逗號運算子來存取Public存取修飾子的屬性和函數。以MyTime類別建立的物件open為例,指定物件屬性Hour、Minute和Second的值,如下所示: open.Hour = 10 open.Minute = 30 open.Second = 30
16-2-1 宣告類別與建立物件-存取物件屬性和方法(方法) • 我們可以使用同樣方式來呼叫方法,如下所示: Console.WriteLine("開張時間: " & _ open.GetTime()) • 因為同一個類別可以建立多個物件,所以每一個物件都可以呼叫自已的方法和存取屬性,如下所示: open.GetTime() close.GetTime()
16-2-2 方法的過載-模組 • Visual Basic程序與函數允許擁有兩個以上的同名方法,只是傳遞的參數個數或資料型態不同,稱為「過載」(Overloads)。在Visual Basic模組宣告程序與函數過載,如下所示: Function Square(ByVal no1 As Integer, _ ByVal no2 As Integer) As Integer Function Square(ByVal no As Integer) As Integer Function Square(ByVal no As Double) As Double • 在上述3個同名函數中,前2個是參數個數不同,後2個是參數資料型態不同,分別是Integer整數和Double浮點數。
16-2-2 方法的過載-類別 • 在類別建立過載方法需在方法名稱前使用Overloads關鍵字,如下所示: Public Overloads Sub SetTime(ByVal h As Integer, _ ByVal m As Integer, ByVal s As Integer) Public Overloads Sub SetTime(ByVal h As Integer, _ ByVal m As Integer) • 上述同名方法的參數個數是3個和2個。
16-2-3 類別的建構子-說明 • Visual Basic基本資料型態在宣告變數時,就會配置所需記憶體空間和指定預設初值。如果類別沒有「建構子」(Constructors),或稱建構函數,在使用子New關鍵字建立物件時,物件預設建構子只是配置記憶體空間,並不會指定成員資料的初值,即初始物件。 • 如果希望類別在建立物件時能夠指定初值,類別需要宣告建構子。建構子是物件的初始方法,在建立物件時會自動呼叫此方法(如果沒有就使用預設建構子)。
16-2-3 類別的建構子-特點 • 建構子沒有傳回值,換句話說,它一定是Sub程序。 • 不論類別名稱,建構子一定是名為New的程序,例如:類別MyTime的建構子是New()。 • 建構子通常是使用Public修飾子進行宣告,事實上,建構子可以使用任何存取修飾子。 • 建構子支援過載,可以擁有多個同名建構子,只是擁有不同參數型態和個數。
16-2-3 類別的建構子-範例 • 建構子程序的程式碼撰寫方式和其他成員方法相同,不過,建構子過載,並不需使用Overloads關鍵字,如下所示: Public Sub New() Public Sub New(ByVal h As Integer, _ ByVal m As Integer) Public Sub New(ByVal h As Integer, _ ByVal m As Integer, _ ByVal s As Integer)
16-2-4 類別的靜態成員-說明 • 類別的靜態成員(Static Member)是一種特殊成員,這些成員不需要建立物件,就可以使用類別名稱來存取和呼叫,例如:之前說明的Math數學類別和Console類別的WriteLine()方法。 • Visual Basic是使用Shared關鍵字來宣告類別的靜態成員,或稱為類別的成員。
16-2-4 類別的靜態成員-範例 • 例如:在Student類別宣告靜態成員Count和NumOfStudents()方法,如下所示: Class Student Private Name As String Private Shared Count As Integer ……… ' 靜態成員方法,也稱為類別方法 Public Shared Function NumOfStudents() As _ Integer Return Count End Function End Class
16-2-4 類別的靜態成員-呼叫 • 因為是靜態成員,所以程式碼可以使用類別名稱Student來呼叫,如下所示: Console.WriteLine("學生數: " & _ Student.NumOfStudents())
16-2-5 部分類別-主要類別 • 部分類別(Partial Class)允許同一個類別分割成多個檔案。主要類別的宣告如同一般類別,例如:MyName類別宣告,如下所示: Class MyName Private FirstName, LastName As String Public Sub New(ByVal f As String, _ ByVal l As String) FirstName = f LastName = l End Sub Public Sub PrintName() …… End Sub End Class
16-2-5 部分類別-部分類別 • 在部分類別需要使用Partial關鍵字進行類別宣告,如下所示: Partial Class MyName Public Sub PrintFirstName() Console.WriteLine("名: " & FirstName) End Sub End Class • 上述程式碼是部分類別宣告,類別名稱與主要類別相同,只是新增PrintFirstName()成員方法。請注意!雖然原始程式碼分割成多個檔案,但在編譯時,仍然是組合成完整類別後才進行編譯。
16-3 類別的繼承 • 16-3-1 類別繼承的基礎 • 16-3-2 實作類別的繼承
16-3-1 類別繼承的基礎-說明 • 類別如果是繼承自其他類別,我們稱此類別為繼承類別的「子類別」(Subclass)或「延伸類別」(Derived Class),繼承的類別稱為「父類別」(Superclass)或「基礎類別」(Base Class),例如:類別Car是繼承自類別Vehicle,其繼承關係如右圖所示:
16-3-1 類別繼承的基礎-兄弟類別 • 如果有多個子類別繼承同一個父類別,則每一個子類別稱為「兄弟類別」(Sibling Classes),如下圖所示:
16-3-2 實作類別的繼承-父類別 Public Class TextLine Public Line As String ' 建構子(1) Public Sub New() Line = "" End Sub ' 建構子(2) Public Sub New(ByVal text As String) Line = text End Sub ……… End Class
16-3-2 實作類別的繼承-類別的繼承(語法) • 在Visual Basic可以建立新類別檔(也可以在同一個檔案)來繼承已經存在的類別,其宣告語法如下所示: Public Class 子類別名稱 Inherits父類別名稱 ……‘額外的成員資料和方法 End Class • 上述語法使用Inherits關鍵子擴充父類別的宣告。
16-3-2 實作類別的繼承-類別的繼承(子類別) • MyLine子類別是繼承自TextLine類別,如下所示: Public Class MyLine Inherits TextLine ' 建構子 Public Sub New() MyBase.New() End Sub ……… End Class • 子類別可以使用MyBase呼叫父類別的建構子、方法和屬性。
16-3-2 實作類別的繼承-覆寫父類別的方法(父類別) • 當我們建立子類別繼承父類別來擴充其功能時,對於父類別的方法,如果希望保留方法名稱,只是更改其功能,在父類別的方法可以使用Overridable關鍵字來宣告,表示方法可以覆寫,如下所示: Public Class TextLine Public Line As String ' 建構子(1) ………… ' 可覆寫的方法 Public Overridable Sub ShowText() Console.WriteLine(LCase(Line)) End Sub End Class
16-3-2 實作類別的繼承-覆寫父類別的方法(子類別) • 使用Overrides關鍵字來覆寫方法,如下所示: Public Class MyLine Inherits TextLine ' 建構子 ………… ' 覆寫方法 Public NotOverridable Overrides Sub ShowText() Console.WriteLine(MyBase.Line) End Sub End Class • NotOverridable關鍵字表示此方法不能再被子類別覆寫。
16-4 抽象類別與介面 • 16-4-1 抽象類別與抽象方法 • 16-4-2 介面
16-4-1 抽象類別與抽象方法-說明 • 抽象類別(Abstract Classes)並不能建立物件,只能繼承抽象類別來宣告子類別。Visual Basic抽象類別是使用MustInherit關鍵字來宣告類別,內含MustOverride關鍵字宣告的抽象方法。 • 抽象方法只是原型宣告,其實作程式碼是位在子類別,而且繼承的子類別一定要實作抽象方法。
16-4-1 抽象類別與抽象方法-抽象類別Shape MustInherit Class Shape Public X As Integer Public Y As Integer ' 建構子 ……… MustOverride Sub Area() ' 抽象方法 End Class • Shape類別定義點(Point)座標X和Y,並且提供抽象方法Area()計算形狀的面積,但是並沒有方法的程式區塊。
16-4-1 抽象類別與抽象方法-子類別Circle Class Circle : Inherits Shape Public R As Integer ……… Public Overrides Sub Area() Console.WriteLine("圓面積: " & _ (3.1415 * R * R)) End Sub End Class • 上述子類別Circle定義圓形,除了圓心座標外,新增成員資料半徑R,並且實作Area()抽象方法來計算圓面積。
16-4-2 介面-說明 • 介面(Interface)可以在類別繼承架構定義類別行為,在介面宣告的方法是一種抽象方法,實作介面的類別需要實作「所有」抽象方法。
16-4-2 介面-宣告 • IArea和IPrint介面宣告,如下所示: Interface IArea Sub Area() End Interface Interface IPrint Sub Print() End Interface • 上述介面宣告是使用Interface關鍵字,其宣告內容是抽象方法(表示尚未實作)。一個類別可以實作一個或多個介面,如果有多個介面,請使用","號分隔。
16-4-2 介面-實作介面 • 宣告Rectangle類別實作IArea和IPrint介面,如下所示: Class Rectangle Implements IArea, IPrint ……… Public Sub Area() Implements IArea.Area Console.WriteLine("長方形面積:" & (Height * Width)) End Sub Public Sub Print() Implements IPrint.Print Console.WriteLine("長方形的長:" & Height) Console.WriteLine("長方形的寬:" & Width) End Sub End Class
16-5 多形的實作-說明 • 「多形」(Ploymorphism)是物件導向程式設計重要且複雜的觀念,它可以讓應用程式更容易擴充,一個同名方法,就可以處理不同資料型態的物件,並且產生不同的操作。 • 多形是物件導向技術中最複雜的觀念,在這一節筆者準備使用類別繼承的覆寫來實作多形,它是繼承抽象類別建立的多形。
16-5 多形的實作-抽象類別Shape • Shape抽象類別宣告,如下所示: MustInherit Class Shape MustOverride Sub Area() End Class • 上述抽象類別定義抽象方法Area()。