回答:
::
基本的には名前空間解決演算子です。モジュール内のアイテム、またはクラス内のクラスレベルのアイテムにアクセスできます。たとえば、次の設定があるとします。
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
モジュール内で呼び出されるクラス(これは、Railsソースのactiverecord-nnn / lib / active_record / base.rbにあります)ActiveRecord
ActiveRecord::Base
::の一般的な用途は、モジュールで定義された定数にアクセスすることです。
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は制約に対して動的すぎます。
いいえ、すべてのメソッドにアクセスするのではなく、「解決」演算子です。つまり、これを使用して、定数/静的シンボルのスコープ(または言うことができる場所)を解決します。
たとえば、最初の行では、Railsはそれを使用してActiveRecord.Module内のBaseクラスを検索し、2番目の行ではRoutesクラスのクラスメソッド(静的)を検索するために使用されます。
何かを公開するために使用されるのではなく、スコープの周りにあるものを「見つける」ために使用されます。
驚いたことに、ここでの10の回答はすべて同じことを言っています。'::'は名前空間解決演算子であり、そうです。しかし、定数ルックアップアルゴリズムに関しては、名前空間解決演算子について理解しなければならない1つの問題があります。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つのモジュールから定数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