2010-12-20 63 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。