Google Prettify

2014-08-17

淺淡物件導向



談到物件導向,大部份的人,所知道的,應該是:
  • 封裝
  • 繼承
  • 多型
讓我由另外一種角度來看物件導向(Object Oriented)。

首先要知道的是:一般來說,物件包含了至少2種以上的東西:
  1. 方法
  2. 屬性
方法,有些地方稱為函數、函式、function、method。
屬性,有些地方稱為property、attribute、message。

這裡傾向用操作methodproperty來說明。他們的關係是「物件靠method來操作 property」。不論這個操作是「傳遞」、「接收」、「取得」、「變更」或是其他的動作

在我們繼續討論之前,先講一下案例:舉例來說,我現在有一個任務,必需產生一個時間序列。如下:

 於是我寫了一個class (TimeSeriesPoint),代表時間序列中的點。這個點有2個部份是我所需要關心的:一個是X軸所表示的日期,另一個是Y軸所表示的值。 x、y 就是TimeSeriesPoint prperty

(日期的部份使用了另外的類別自訂類別,但這不在本次討論的範圍內)

另外有一個class(TimeSeries),代表著時間序列。針對於時間序列這個class,我期望他可以做三件事:
  1. 可以透過數字索引知道這個。例如輸入4可以知道時間序列的第4個點的值是36。
  2. 可以透過輸入像”2014/3/7”這樣的資訊,找到相對應的點。
  3. 可以找到”2014/3/7”後N點的資料。
因此我根據這樣的需求,產生了一個class,在這個calss中會透過這些method來取得不同的TimeSeriesPoint:

 getTimeSeriesPoint、next就是TimeSeries的method

以上是我們的案例。接下來,我們來進行探討。

一、首先,物件導向,顧名思義,就是以程式來代表物件。案例裡,TimeSeries代表著那一條線、而TimeSeriesPoint代表著線上的點。針對於這2個物件,於是產生了2個class。不過在物件導向中,並不是只有「可視」的東西才會被物件化,更常見的是「概念」也會被物件化。例如 「連線」等。通常物件都會是以名詞來表達,而method則通常會以動詞來做為開頭,說明這個名詞可以有這樣的行為。即使是handele這樣的一個概念,也都會使用handler 來表達;針對於不同的handler就會有不同的property 與method 產生。

二、Java 101,所有的class都是繼承於Object這個class,有留意到關鍵字了嗎?這就是「繼承」。我們每天都在用,可是用的很不自覺。

三、我們知道getTimeSeriesPoint/next 這2個method(其實是3個method)他們的功能了,可是裡面該怎麼做,可能需要晚點再想,或是其他調用的人根本不需要在乎,透過Java的權限(public/ protected/ private) 與方法,我們將他「封裝」起來。封裝用另外一種講法,就是讓人搞不清楚不知道你裡面在做什麼。一個最常見的理由是其他人不需要知道。就好比一般物件導向課程裡所說的:「你只要知道車子怎麼開,不用知道車子怎麼動」。

 四、getTimeSeriesPoint這個method(method)可以有2種參數輸入方式,一種是只有單純輸入int,一種是輸入String。這種可以透過輸入不同的參數,來使用不同的method,就是多型。有些人可能會覺得,是否可以使用 getTimeSeriesPointByIndex 與 getTimeSeriesPointByString 2種不同名稱 的method 是否會更好?而且可以光透過名稱可以表示出更多的意思。其實這個多型的例子沒有舉的很合適。另外一個我們在課堂上常舉的的例子,就是 ”+” 這個運算子,這個例子會更貼切於多型這個概念。

 “+”這個運算子,可以做為文字相加,例如
“2” + “1” =21

也可以算為數字相加:
2 + 1 =3

 “+” 可以依照你輸入的運算元型別,或是另一種說法─依照你輸入的參數,看是數字還是文字,產生不同的結果。

 多型在Java 一般的method上,常可以看到,但也不一定需要使用到多型;這只是一種選擇;但在有些地方,例如”+”這樣的運算,就幾乎可以說是一定要使用多型這樣的功能了。

 物件導向差不多講完了。不過我想再提一下物件導向另外一個重點:責任區分

 其實next() 的功能,該由誰來做,是一個模糊的地方。他可以是TimeSeries.next(TimeSeriesPoint, 1):
public class TimeSeries{
    public TimeSeriesPoint next(TimeSeriesPoint timeSeriesPoint, int i) {
      ...
    }
}
中文解釋會是: TimeSeries 去尋找特定 TimeSeriesPoint的下一個點。

但如果是TimeSeriesPoint.next(1) 似乎也算說的過去。
public class TimeSeriesPoint {
    public TimeSeriesPoint next(int i) {
        ...
    }
}
 中文解釋是:TimeSeriesPoint去尋找自己的的下一個點。

在物件導向中,相對應的「解釋」是一件很重要的事;這說明了這個method他所應該負責的事情;如果解釋的恰當,也可以透過這個「解釋」來判斷這所「負責的事情」是不是該由這個class來負責。PS: 當然解釋不一定要要中文啦…。

軟體設計的一個有趣的地方就在這裡:「這樣做也可以,那樣做也可以」。當然將next()視為是TimeSeries的方法有他的好處,當然也有他的缺點,放在TimeSeriesPoint上也是如此。基本上軟體設上很多時候都是一個trade-off的選擇:有一好沒兩好、魚與熊掌不可兼得。我們時常花不少心思與時間在決定這些設計。

沒有留言 :

您或許對這些有興趣

Related Posts with Thumbnails

最後

謝謝您的閱讀,希望您可以有豐富的收獲。