2010-12-20 59 views
72

Ruby(公共,受保護和私有方法)中的方法可見性在this blog post等地方得到了很好的解釋。但是在Ruby on Rails中,由於框架的設置方式,它與普通的Ruby應用程序看起來略有不同。那麼,在Rails模型,控制器,助手,測試等中,何時/不適合使用受保護或私有方法?Rails中的受保護和私有方法

編輯:感謝迄今爲止的答案。我理解Ruby中protected和private的概念,但我更多地瞭解這些類型的可見性在Rails應用程序的不同部分(模型,控制器,幫助程序,測試)的上下文中使用的典型方式的解釋。 。例如,公共控制方法是用於需要由多個控制器訪問「輔助方法」等

回答

91

對於模型,其思想是公共方法是類的公共接口。公共方法旨在被其他對象使用,而受保護/私有方法將從外部隱藏。

這與其他面嚮對象語言中的做法相同。

對於 控制器和 測試,請按照您的要求進行。 控制器和 測試類只是實例化和框架調用( 是的,我知道你理論上可以從視圖中獲得控制器,但如果你這樣做,無論如何,奇怪的東西 )。由於沒有人會直接創造這些東西,所以沒有什麼可以「保護」。

增編/更正:對於控制器,則應選中「幫手」的方法爲 保護 私人的,只有行爲本身應該是公開的。框架永遠不會將任何傳入的HTTP調用路由到不公開的動作/方法,因此您的幫助器方法應該以這種方式受到保護。

對於幫助者來說,如果某個方法是受保護的或私有的,它們將沒有區別,因爲它們總是被稱爲「直接」。

當然,如果它讓事情變得更容易理解,您可以在所有這些情況下標記受保護的內容。

+0

「*對於控制器,您應該將」幫助器「方法標記爲受保護的,並且只有操作本身應該公開。*「您是否建議不要在控制器中使用任何私人方法?或者我不應該從字面上閱讀? – Dennis 2014-05-29 21:09:06

+0

現在我只用私人。在大多數地方,受保護的和私人的交替使用;但受到保護會帶來一種我在現實世界中從未需要的奇怪行爲。 – averell 2014-07-01 15:58:19

+1

我傾向於只使用私人。這也遵循某些指導原則,例如[Thoughtbot的「在定義控制器方法時使用private而不是protected」。](https:// github。COM/thoughtbot /引導/ BLOB/98eede4e2d93d76b0e9e5bdedb6899985de6d574 /風格/ README.md#L196) – Dennis 2014-07-04 17:45:57

9

保護和 私人是細微的區別的操作方法,在應用程序控制器的保護方法。如果方法是受保護的,則可以由定義類或其子類的任何 實例調用該方法。如果一個方法是私有的,它可以 僅在調用對象的上下文 被稱爲---這是從來沒有 可以直接訪問另一個對象 實例的私有方法,即使 對象是相同 類爲呼叫者,召集者。對於受保護的 方法,可從 同一類別的對象(或 兒童)訪問它們。

http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Classes#Declaring_Visibility

+2

感謝您的鏈接。但是我更想知道如何在Ruby on Rails中專門工作(公共控制器方法被視爲操作方法,應用程序控制器中的受保護方法可以被其他控制器使用等) – jrdioko 2010-12-21 00:01:58

+3

在最後一種情況下,應用程序控制器可以被其他控制器使用「,這是因爲其他控制器(通常)從* ApplicationController繼承,所以它們實際上擁有所有這些方法。他們沒有從application_controller訪問它們:這不會被實例化。它純粹用作父代繼承。 – 2010-12-21 10:17:08

57

如果你想沒有其他人,但self使用方法,您可以使用一個私有方法。如果您希望只有self and is_a?(self)可以撥打電話,您可以使用受保護的方法。

如果您有一個「虛擬」初始化方法,那麼可以很好地使用保護。

class Base 
    def initialize() 
     set_defaults() 
     #other stuff 
    end 

    protected 
    def set_defaults() 
     # defaults for this type 
     @foo = 7 
     calculate_and_set_baz() 
    end 

    private 
    def calculate_and_set_baz() 
     @baz = "Something that only base classes have like a file handle or resource" 
    end 
end 

class Derived < Base 
    protected 
    def set_defaults() 
     @foo = 13 
    end 
end 

@foo將會有不同的值。和衍生的實例將不會有@baz

更新: 自從我寫這一點,有些事情在Ruby中2.0+亞倫帕特森變化具有優良的寫了http://tenderlovemaking.com/2012/09/07/protected-methods-and-ruby-2-0.html

+9

愛你如何說'自我和is_a?(self)'。我一直將受保護的方法解釋爲在兒童課程中可用。 – 2010-12-21 11:25:46

+14

注意!這是其他語言的重要區別:子類中的私有方法也可用。私有和受保護的唯一區別是你可以用「self.set_defaults」調用受保護的方法,而私有方法只能被稱爲「set_defaults」。 – averell 2011-01-06 09:03:19

+0

一個很好的答案,但甚至沒有包含單詞Rails這是問題的要點 – 2011-01-06 13:41:26

2

你似乎有的一個好主意應用於方法的類可見性(public/protected/private)的語義。我可以提供的只是我在Rails應用程序中實現它的方式的簡要概述。

我在基本應用程序控制器中實現受保護的方法,以便任何控制器都可以通過過濾器調用它們(例如before_filter:method_foo)。以類似的方式,我定義了模型的受保護方法,我想在它們全部繼承的基礎模型中使用它們。

2

雖然動作需要是控制器的公共方法,但並非所有的公共方法都必然是動作。如果使用類似/:controller/:action/:id的全線路徑或者它被禁用(Rails 3中的默認路徑),那麼可以使用hide_action,那麼只有具有顯式路由的方法纔會被調用。

如果您將控制器實例傳遞給其他庫(如Liquid模板引擎),這可能很有用,因爲您可以提供公共接口,而不必使用Liquid濾鏡和標籤中的send。