Answers:
::
基本上是名称空间解析运算符。它允许您访问模块中的项目或类中的类级别的项目。例如,假设您有以下设置:
module SomeModule
module InnerModule
class MyClass
CONSTANT = 4
end
end
end
您可以CONSTANT
从模块外部访问SomeModule::InnerModule::MyClass::CONSTANT
。
它不会影响在类上定义的实例方法,因为您可以使用不同的语法(点.
)来访问它们。
相关说明:如果要返回顶级命名空间,请执行以下操作::: SomeModule – Benjamin Oakes
::
用于名称空间解析,例如std::cout << "Hello World!";
::SomeModule
这个简单的例子说明了这一点:
MR_COUNT = 0 # constant defined on main Object class
module Foo
MR_COUNT = 0
::MR_COUNT = 1 # set global count to 1
MR_COUNT = 2 # set local count to 2
end
puts MR_COUNT # this is the global constant: 1
puts Foo::MR_COUNT # this is the local constant: 2
::
使您可以访问在另一个类或模块内定义的常量,模块或类。它用于提供名称空间,以使方法和类名不会与不同作者的其他类冲突。
当您ActiveRecord::Base
在Rails中看到它时,意味着Rails具有类似
module ActiveRecord
class Base
end
end
即Base
在模块内部调用的类ActiveRecord
,然后将该类引用为ActiveRecord::Base
(您可以在activerecord-nnn / lib / active_record / base.rb的Rails源代码中找到该类)
::的常见用法是访问模块中定义的常量,例如
module Math
PI = 3.141 # ...
end
puts Math::PI
该::
运营商不允许你的方法绕过可视性标记为私有或保护。
class MyClass < ActiveRecord::Base
,是否意味着MyClass仅继承类的方法,而不继承ActiveRecord模块中的任何方法?
class Foo; Baz = 42; def self.Baz; "Baz method!"; end; end
(完全有效)Foo::Baz # => 42
和Foo.Baz # => "Baz method!"
。注意Foo::Baz()
(带括号)也会调用该方法。
如果仅使用::公开任何内容,范围(私有,受保护)有什么用?
在Ruby中,所有内容都可以公开,并且可以在其他任何地方进行修改。
如果您担心类可以从“类定义”之外进行更改的事实,那么Ruby可能不适合您。
另一方面,如果您对Java的类被锁定感到沮丧,那么Ruby可能就是您想要的。
attr_accessor
只是使方法修改了变量。(然后再来instance_eval
)
instance_eval
。但是还有instance_variable_get
和instance_variable_set
。Ruby对于约束来说太动态了。
除了以前的答案外,它是::
用于访问实例方法的有效Ruby 。以下所有条件均有效:
MyClass::new::instance_method
MyClass::new.instance_method
MyClass.new::instance_method
MyClass.new.instance_method
根据最佳实践,我认为仅建议使用最后一个。
不,它不是访问所有方法,而是一个“分辨率”运算符,也就是说,您可以使用它来解析恒定/静态符号的范围(可以说的位置)。
例如,在您的第一行中,Rails使用它在ActiveRecord.Module中找到基类,在第二行中,它用于查找Routes类的类方法(静态),等等。
它不用于公开任何内容,而是用于在示波器范围内“定位”东西。
出乎意料的是,这里的所有10个答案都说相同的话。'::'是名称空间解析运算符,是的。但是当涉及到常量查找算法时,您必须意识到名称空间解析运算符。正如Matz在他的《 Ruby编程语言》一书中所描述的那样,持续查找有多个步骤。首先,它在引用该常量的词法范围内搜索常量。如果未在词法范围内找到该常量,则将搜索继承层次结构。由于采用了这种恒定查找算法,因此我们在下面得到了预期的结果:
module A
module B
PI = 3.14
module C
class E
PI = 3.15
end
class F < E
def get_pi
puts PI
end
end
end
end
end
f = A::B::C::F.new
f.get_pi
> 3.14
尽管F继承自E,但是B模块在F的词法范围内。因此,F实例将引用模块B中定义的常量PI。现在,如果模块B未定义PI,则F实例将引用PI超类E中定义的常数。
但是,如果我们使用'::'而不是嵌套模块呢?我们会得到相同的结果吗?没有!
通过在定义嵌套模块时使用名称空间解析运算符,嵌套模块和类不再位于其外部模块的词法范围内。如下所示,A :: B中定义的PI不在A :: B :: C :: D的词法范围内,因此,当尝试在get_pi实例方法中引用PI时,我们得到未初始化的常量:
module A
end
module A::B
PI = 3.14
end
module A::B::C
class D
def get_pi
puts PI
end
end
end
d = A::B::C::D.new
d.get_pi
NameError: uninitialized constant A::B::C::D::PI
Did you mean? A::B::PI
module Amimal
module Herbivorous
EATER="plants"
end
end
Amimal::Herbivorous::EATER => "plants"
::用于创建范围。为了从2个模块访问Constant EATER,我们需要调整模块的范围以达到常量
Ruby on Rails ::
用于名称空间解析。
class User < ActiveRecord::Base
VIDEOS_COUNT = 10
Languages = { "English" => "en", "Spanish" => "es", "Mandarin Chinese" => "cn"}
end
要使用它:
User::VIDEOS_COUNT
User::Languages
User::Languages.values_at("Spanish") => "en"
另外,其他用法是:使用嵌套路由时
OmniauthCallbacksController
在用户下定义。
并路由为:
devise_for :users, controllers: {omniauth_callbacks: "users/omniauth_callbacks"}
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
end