Ruby-on-rails Rails 中的受保护和私有方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4495078/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 23:57:03  来源:igfitidea点击:

Protected and private methods in Rails

ruby-on-railsrubyvisibilityprivateprotected

提问by jrdioko

Method visibility in Ruby (public, protected, and private methods) has been well explained in places like this blog post. But in Ruby on Rails it seems slightly different than it would be in a regular Ruby application because of the way the framework is set up. So, in Rails models, controllers, helpers, tests, etc., when is/isn't it appropriate to use protected or private methods?

Ruby 中的方法可见性(公共、受保护和私有方法)已在此博客文章等地方得到了很好的解释。但是在 Ruby on Rails 中,由于框架的设置方式,它似乎与在常规 Ruby 应用程序中的情况略有不同。那么,在 Rails 模型、控制器、助手、测试等中,何时/不适合使用受保护或私有方法?

Edit: Thanks for the answers so far. I understand the concept of protected and private in Ruby, but I'm looking more for an explanation of the typical way those types of visibility are used within the context of the various pieces of a Rails app (models, controllers, helpers, tests). For example, public controller methods are action methods, protected methods in the application controller are used for "helper methods" that need to be accessed by multiple controllers, etc.

编辑:感谢您到目前为止的答案。我了解 Ruby 中 protected 和 private 的概念,但我正在寻找更多关于在 Rails 应用程序的各个部分(模型、控制器、助手、测试)的上下文中使用这些类型的可见性的典型方式的解释. 例如,公共控制器方法是动作方法,应用程序控制器中的受保护方法用于需要多个控制器访问的“辅助方法”等。

回答by averell

For models, the idea is that the public methods are the public interface of the class. Public methods are intended to be used by other objects, while protected/private methods are to be hidden from the outside.

对于模型,其思想是公共方法是类的公共接口。公共方法旨在供其他对象使用,而受保护/私有方法则对外部隐藏。

This is the same practice as in other object-oriented languages.

这与其他面向对象语言中的做法相同。

For controllers andtests, just do as you please. Both controller andtest classes are only instantiated and called by the framework (yes, I know you can theoretically get the controller from the view, but if you do that, something is strange anyway). Since no one will ever create those things directly, there's nothing to "protect" against.

对于控制器和测试,随心所欲。控制器和测试类都只被框架实例化和调用(是的,我知道理论上你可以从视图中获取控制器,但如果你这样做,无论如何都会有些奇怪)。因为没有人会直接创造这些东西,所以没有什么可以“保护”的。

Addendum/Correction:For controllers, you should mark the "helper" methods as protectedprivate, and only the actions themselves should be public. The framework will never route any incoming HTTP calls to actions/methods that are not public, so your helper methods should be protected in that way.

附录/更正:对于控制器,您应该将“助手”方法标记为受保护的私有方法,并且只有操作本身应该是公开的。该框架永远不会将任何传入的 HTTP 调用路由到非公开的操作/方法,因此您的辅助方法应该以这种方式受到保护。

For helpers it will make no difference if a method is protected or private, since they are always called "directly".

对于助手来说,方法是受保护的还是私有的没有区别,因为它们总是被“直接”调用。

You can mark stuff protected in all those cases if it makes things easier for you to understand, of course.

当然,如果它使您更容易理解,您可以在所有这些情况下标记受保护的内容。

回答by EnabrenTane

You use a private method if you want no one else but selfto use a method. You use a protected method if you want something only self and is_a?(self)s can call.

如果您不想要其他人而self只使用一种方法,则可以使用私有方法。如果你想要只有self and is_a?(self)s 可以调用的东西,你可以使用受保护的方法。

A good use of protected might be if you had a "virtual" initialization method.

如果您有“虚拟”初始化方法,则可以很好地使用 protected 。

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 will have different values. and the Derived instances will not have @baz

@foo 会有不同的值。并且派生实例不会有@baz

Update: Since I wrote this, some things have changed in Ruby 2.0+ Aaron Patterson has an excellent write up http://tenderlovemaking.com/2012/09/07/protected-methods-and-ruby-2-0.html

更新:自从我写这篇文章以来,Ruby 2.0+ 中的一些事情发生了变化 Aaron Patterson 写了一篇很棒的文章http://tenderlovemaking.com/2012/09/07/protected-methods-and-ruby-2-0.html

回答by nunopolonia

The difference between protected and private is subtle. If a method is protected, it may be called by any instance of the defining class or its subclasses. If a method is private, it may be called only within the context of the calling object---it is never possible to access another object instance's private methods directly, even if the object is of the same class as the caller. For protected methods, they are accessible from objects of the same class (or children).

protected 和 private 之间的区别是微妙的。如果一个方法是受保护的,它可以被定义类或其子类的任何实例调用。如果一个方法是私有的,它只能在调用对象的上下文中被调用——永远不可能直接访问另一个对象实例的私有方法,即使该对象与调用者属于同一类。对于受保护的方法,它们可以从同一类(或子类)的对象访问。

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

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

回答by Sasha

You seem to have a good idea of the semantics of class visibility (public/protected/private) as applied to methods. All I can offer is a quick outline of the way I implement it in my Rails apps.

您似乎对应用于方法的类可见性(公共/受保护/私有)的语义有很好的了解。我所能提供的只是我在 Rails 应用程序中实现它的方式的快速概述。

I implement protected methods in the base application controller so they can get called by any controller via filters (e.g. before_filter :method_foo). In a similar way, I define protected methods for models that I want to use in all of them in a base model that they all inherit from.

我在基本应用程序控制器中实现了受保护的方法,因此它们可以被任何控制器通过过滤器(例如 before_filter :method_foo)调用。以类似的方式,我为我想在所有模型中使用的模型定义了受保护的方法,这些方法都从它们继承的基本模型中使用。

回答by pixeltrix

Although actions need to be public methods of a controller, not all public methods are necessarily actions. You can use hide_actionif you're using a catch-all route like /:controller/:action/:idor if it's disabled (the default in Rails 3) then only methods with explicit routes will be called.

尽管操作需要是控制器的公共方法,但并非所有公共方法都必须是操作。您可以使用hide_action,如果你使用像一个包罗万象的路线/:controller/:action/:id或者如果它是禁用(在Rails 3中默认),那么只能用显式路由方法将被调用。

This can be useful if you're passing the controller instance to some other library like the Liquid template engine as you can provide a public interface rather than having to use send in your Liquid filters and tags.

如果您将控制器实例传递给其他库(如 Liquid 模板引擎),这会很有用,因为您可以提供公共接口,而不必在 Liquid 过滤器和标签中使用发送。