2011-06-05 89 views
7

我用來做幾乎所有我的類變量的私人和創建「包裝」函數獲取/設置他們:私有變量的優點/缺點?

class Something{ 
    private $var; 

    function getVar(){ 
    $return $this->var; 
    } 

} 

$smth = new Something(); 
echo $smth->getVar(); 

我看到有很多人做到這一點,所以我落得這樣做同樣:)

是否有使用它們這種方式與任何優勢:

class Something{ 
    public $var; 
} 
$smth = new Something(); 
echp $smth->var; 

我知道你不能訪問它們直接在類的外部私有手段,但對我來說似乎沒有如果變量是從任何地方訪問非常重要......

那麼,有沒有其他隱藏的優勢,我缺少私有變量?

+0

您可以在幾個月前剛剛瞭解類的問題中找到您的答案:http://stackoverflow.com/questions/5034951/how-should-i-write-classes-c – Lockhead 2011-06-05 13:02:25

回答

3

如果你想在公共getter和setter中使用私有變量,或者你只是想直接聲明一個變量爲公共變量,它就不同於每種情況。

使用「getters」和「setter」可能會比較好的原因是,如果您想要控制某人何時訪問數據。

舉個例子,假設你有這樣的:

public setBirthday($date) 

然後你就可以確保在傳遞給二傳手日期是一個有效的生日。

但你不能,如果你只是將變量聲明爲public這樣

public $birthday; 

基於評論

另外,如果決定從包含日期到 秒數因爲1/1/1970一個 串改變 內部存儲機構,就可以 仍然呈現日期外部 在同一如果你使用 封裝,但不是如果你直接暴露 變量。現在,每個 代碼直接觸及內部變量 現在會被破壞。

這意味着,如果內部存儲機制將改爲從1/1/1970秒的數字,那麼你不必改變「外部API」。究其原因是因爲你擁有了它完全的控制:

public getBirthday() { 
    // you can still return a string formatted date, even though your 
    // private variable contains number of seconds from 1/1/1970 
} 
+0

此外,如果您決定將內部存儲機制從包含日期的字符串更改爲自1970年1月1日以來的秒數,則仍然可以使用封裝方式在外部以相同的方式顯示日期,但如果您使用封裝直接的變量。現在每一段直接觸及內部變量的代碼都會被破壞。 – tvanfosson 2011-06-05 13:08:28

+0

好點!我編輯了我的問題來解釋它。 – Fredrik 2011-06-05 13:25:59

2

它是從用於外部變化的變量中去定義實現類的內部變量。也有protected變量,這些變量用於內部使用,並通過對類的擴展使用。

我們使變量private這樣只有類中的代碼可以修改變量,保護來自外部的干擾,保證變量的控制和預期行爲。

4

這就是所謂的encapsulation這是一件非常好的事情。封裝將您的課程從其他課程中分離出來,將其與內部部件混爲一談,它們只會通過您的方法獲得您允許的訪問權限。它還可以保護他們免受可能對班級內部造成的變化。如果對變量的名稱或用法進行更改,如果沒有封裝,則該更改會傳播到所有其他使用該變量的類。如果你迫使他們通過一種方法,那麼至少有一種機會可以處理方法的變化,並保護其他類不受變化的影響。

3

訪問修飾符在腳本語言中沒有太多意義。許多實際的面嚮對象語言,如Python或Javascript,都沒有它們。

而幼稚的getter/setter方法的普遍性僅僅是由於PHP沒有提供明確的構造。 http://berryllium.nl/2011/02/getters-and-setters-evil-or-necessary-evil/

+2

他們當他們被強制執行時是完全有意義的,就像他們在其他語言中一樣。 – Orbling 2011-06-05 13:04:34

+0

他們的過度使用常常表明對核心OOP概念的誤解,如消息傳遞和封裝的目的。 – mario 2011-06-05 13:12:19

+0

@mario:我不同意,所有實例化的變量都應該有一個訪問修飾符,注意它們的作用域。 – Orbling 2011-06-05 13:16:24

2

封裝的目的是隱藏其他對象的對象的內部結構。這個想法是,對象的外部足跡構成了它的定義類型,將它想象爲與其他對象的契約。在內部,它可能不得不跳過一些箍環來提供向外的功能,但這與其他對象無關。他們不應該混淆它。

例如,假設您有一個提供銷售稅計算的類。基本上是某種公用事業服務對象。它有一些提供必要功能的方法。

在內部,該類正在打一個數據庫以獲取某些值(例如,給定轄區的稅收)以執行計算。它可能在內部維護數據庫連接和其他與數據庫相關的事物,但其他類不需要知道這一點。其他類只涉及面向外的功能性合同。

假設稍後數據庫需要替換爲外部Web服務。 (該公司正在開展一項計算銷售稅的服務,而不是在內部進行維護。)由於該類是封裝的,因此可以更改其內部實現以非常輕鬆地使用服務而不是數據庫。該類只需要繼續提供相同的面向外的功能。

如果其他班級正忙於班級的內部工作,那麼重新實施它將會冒險打破系統的其他部分。