實質上鼓勵一下吧

物件導向這個議題已經是老掉牙了,但是實際上會寫物件導向程式的人實在不多,因為即使你不使用物件導向方法程式照樣可以運作,而且使用物件導向方法程式的效能未必好,所以使得大部份的程式設計師即使使用物件導向程式語言還是使用傳統的副程式方法在寫程式。

那麼為甚麼要使用物件導向方法來寫程式呢,我可以大膽的說,物件導向的精髓就在於繼承。使用繼承的技巧可以讓你的程式變得非常容易維護。

那些基礎的事情包含類別、屬性、方法、事件以及物件就不談了,不明白請隨便翻一翻物件導向的書籍都有很清楚的說明,我要談的是繼承,而且是使用VB.NET的語法。這裡我不去討論該怎麼寫產生程式,只是針對物件導向來探討思考邏輯。

還是用之前的例子,寫一個報表產生程式,請參考再談多執行緒這篇文章的內容。

當我們接受了一個程式任務,其實就應該考慮到程式是否會被重複利用,還有怎麼用法。報表產生程式就是一個例子,你不會想要每次公司叫你寫一個新的報表就把程式複製一次,然後改一改吧。雖然這樣也是可行,但是當你複製多了以後,維護起來就會非常痛苦,因為發現一個問題,每一個報表程式都需要去重新審視。

我們先看最簡單的報表結構,一份報表最簡單的就是包含了表頭、表身、表尾三個部份,其中表身的內容最簡單,就是相同類型的資料重複輸出,所以我們可以定義一個類別(大陸稱為類)如下:

Public Class Report
  Public BodyTable As DataTable
  Public Sub RendReport()
    RenderHeader()
    RenderBody()
    RenderFooter()
  End Sub
  Public Sub RenderHeader()
  End Sub
  Public Sub RenderBody()
  End Sub
  Public Sub RenderFooter()
  End Sub
End Class

很簡單對吧,程式開發之初這樣寫是最容易的,不過如果這樣就算完事,那麼你只是個初級班的程式設計師。我們來慢慢改造這個類別,讓他符合物件導向的精神。首先改造的是類別宣告。

Public MustInherit Class ReportBase

改成這樣的原因在於,這個類別將是所有報表類別的基礎,所有報表程式都應該繼承這個類別。而且這個類別不應該被拿來直接使用,所以加了MustInherit關鍵字。

每一個表頭和表尾都可能因為不同的需求會有不同的格式,所以這兩個部份應該是可以被複寫的,也就是說新的類別可以重新寫這一段程式碼。但是有很大的一部份報表應該是長得一樣的,所以這個方法裏面可以寫上公用的部份,所以這個方法可以改造如下:

Public Overridable Sub RenderHeader()
  Dim OutText As String = ""
  OutText += "報表名稱" + vbCrLf
  OutText += string.format("報表日期:{0:yyyy/MM/dd}", Today)
End Sub

其中報表標題的部份,可以用三種手法來呈現,第一種最簡單,用屬性的方式,讓物件在一開始就設定起來,例如:

Public ReportTitle As String

但是屬性是一個比較死的東西,它不能夠在執行的過程中改變,所以可以用第二種手法,事件。簡單的列出程式碼如下:

Public MustInherit Class ReportBase
Public Event RenderTitle(ByRef ReportTitle As String)
Public Overridable Sub RendHeader()
  Dim OutText As String = ""
  Dim ReportTitle As String = ""
  RaiseEvent RenderTitle(ReportTitle )
  OutText += ReportTitle + vbCrLf
  OutText += string.format("報表日期:{0:yyyy/MM/dd}", Today)
End Sub

說實在的這個手法有點醜,因為事件會反映到最外層使用的程式,而且那個程式也未必要去處理這個事件。

第三種手法的思考是,每個報表標題都應該是完全不同的,也就是說沒有可以利用的部份,那麼也就是說新的類別必須去實做每一個報表的標題,因此程式變成:

Public MustInherit Class ReportBase
Public MustOverride Sub RenderTitle(ByRef ReportTitle As String)
Public Overridable Sub RendHeader()
  Dim OutText As String = ""
  Dim ReportTitle As String = ""
  RenderTitle(ReportTitle )
  OutText += ReportTitle + vbCrLf
  OutText += string.format("報表日期:{0:yyyy/MM/dd}", Today)
End Sub

這樣做是寫了一個必須要被新類別實做的事件,因此等於強迫新物件一定要有這個事件。其他的程式內容就不多贅述,接下來就是要實做新的類別,也就是可以被直接使用的類別。

Public Class RobotClientDaily
  Inherits ReportBase
  Public Overrides Sub RenderTitle()
  End Sub
End Class

由於大部份的事情基類都已經做得好好的了,因此只要實做必須要做的部份就可以了,如果有需要特別處理的部份,可以同樣用Overrides關鍵字來複寫事件,並且可以用MyBase物件再去執行原來在基類上面所執行的程式,不用在新的類別中重新撰寫,例如:

Public Overrides Sub RenderTitle()
  MyBase.RenderTitle
End Sub

能夠寫基類的程式設計師並不多,因為他必須考慮到全面性的應用,如果程式寫作經驗不夠是沒有辦法擔任這個任務的,如果有心在程式設計領域提升自己,應該自己多多朝著這個方向去深度研究。

創作者介紹

人生四十宅開始 二號宅

漠哥 發表在 痞客邦 留言(2) 人氣()


留言列表 (2)

發表留言
  • SISSY
  • 求救

    請問在VB6.0中我的程式試不出VBCRLF的效果,是什麼問題呢?
    謝謝解答,感恩不盡!
    程式如下
    Private Sub Command1_Click()
    Dim i, score, sum, max, n As Integer
    sum = 0: max = 0: n = 0
    For i = 1 To 5 Step 1
    score = InputBox("請輸入第" & i & "科成績")
    sum = sum + score
    Text1.Text = "第" & i & "科成績為" & score & vbCrLf
    If score > max Then max = score
    If score >= 60 Then n = n + 1
    Next i
    If Check1.Value = 1 Then Text2.Text = "你這次月考的總分為" & sum & "分" + vbCrLf
    If Check2.Value = 1 Then Text2.Text = "你這次月考的最高分為" & max & "分" + vbCrLf
    If Check3.Value = 1 Then Text2.Text = "你這次月考的及格科目數為" & n & "科" + vbCrLf

    End Sub
  • vb6對我來說已經是很久遠的事情了,可能你的VB6沒有引入常數庫。vbCrLf等同於chr(8)+chr(10),你可以自己宣告一個常數或變數來實現它!

    漠哥 於 2010/01/07 23:07 回覆

  • DCP
  • 新人

    因為 加長開發時間 對小軟體沒幫助
    所以有些人就不用了
    但raiseEvent對一些monitoring之類就有幫助

    針對語法部分
    既然reportTitle是需要的為何不在 new function加入就好了...