このダブルコロン::
とは何ですか?例えば。 Foo::Bar
。
定義 が見つかりました:
::
は単項演算子であり、クラスまたはモジュール内で定義された定数、インスタンスメソッド、およびクラスメソッドに、クラスまたはモジュールの外部からアクセスできます。
::
を使用して何かを公開できる場合、スコープ(プライベート、保護)はどのようなものですか?
::
は、基本的に名前空間解決演算子です。モジュール内のアイテム、またはクラス内のクラスレベルのアイテムにアクセスできます。たとえば、次の設定があったとしましょう:
module SomeModule
module InnerModule
class MyClass
CONSTANT = 4
end
end
end
SomeModule::InnerModule::MyClass::CONSTANT
としてモジュールの外部からCONSTANT
にアクセスできます。
異なる構文(ドット.
)でアクセスするため、クラスで定義されたインスタンスメソッドには影響しません。
関連するメモ:最上位の名前空間に戻りたい場合は、これを実行します。:: SomeModule – Benjamin Oakes
次の簡単な例で説明します。
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
puts Foo::MR_COUNT # this is the local "Foo" constant
::
別のクラスまたはモジュール内で定義された定数、モジュール、またはクラスにアクセスできます。メソッドおよびクラス名が異なる作成者による他のクラスと競合しないように、名前空間を提供するために使用されます。
RailsでActiveRecord::Base
を見ると、Railsには次のようなものがあることを意味します。
module ActiveRecord
class Base
end
end
すなわち、モジュールBase
内のActiveRecord
と呼ばれるクラスは、その後ActiveRecord::Base
として参照されます(これはactiverecord-n.n.n/lib/active_record/base.rbのRailsソースで見つけることができます)
::の一般的な用途は、モジュールで定義された定数にアクセスすることです。
module Math
PI = 3.141 # ...
end
puts Math::PI
::
演算子では、privateまたはprotectedとマークされたメソッドの可視性をバイパスできません。
::を使用して何かを公開できる場合、スコープ(プライベート、保護)はどのような利点がありますか?
Rubyでは、すべてが公開されており、他のどこからでもすべてを変更できます。
「クラス定義」の外部からクラスを変更できるという事実を心配しているなら、Rubyはおそらくあなたには向いていないでしょう。
一方、Javaのクラスがロックされていることに不満を感じているなら、Rubyがおそらくあなたが探しているものです。
いいえ、すべてのメソッドにアクセスするのではなく、「解決」演算子です。つまり、これを使用して、定数/静的シンボルのスコープ(または言うことができる場所)を解決します。
たとえば、最初の行では、RailsはActiveRecord.Module内でBaseクラスを見つけるためにそれを使用し、2番目の行ではRoutesクラスなどのクラスメソッド(静的)を見つけるために使用されます。
何かを公開するために使用されるのではなく、スコープの周りにあるものを「見つける」ために使用されます。
以前の回答に加えて、::
を使用してインスタンスメソッドにアクセスすることは有効なRubyです。以下はすべて有効です。
MyClass::new::instance_method
MyClass::new.instance_method
MyClass.new::instance_method
MyClass.new.instance_method
ベストプラクティスに従って、最後の1つだけが推奨されると信じています。
定義は、プロジェクトにリンクされている他のコードと衝突しないようにすることです。それはあなたが物事を別々に保つことができることを意味します。
たとえば、コード内で「run」というメソッドを1つ持つことができますが、リンクした他のライブラリで定義された「run」メソッドではなく、メソッドを呼び出すことができます。
驚くべきことに、ここでの10個の回答はすべて同じことを言っています。 '::'は名前空間解決演算子であり、はい、本当です。しかし、定数検索アルゴリズムに関しては、名前空間解決演算子について理解しなければならない落とし穴が1つあります。 Matzが彼の著書「The Ruby Programming Language」で説明しているように、定数検索には複数のステップがあります。最初に、定数が参照されるlexical scopeで定数を検索します。字句スコープ内で定数が見つからない場合は、継承階層を検索します。この定数ルックアップアルゴリズムにより、以下で期待される結果が得られます。
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
Ruby on Railsは、名前空間の解決に::を使用します。
class User < ActiveRecord::Base
VIDES_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
module Amimal
module Herbivorous
EATER="plants"
end
end
Amimal::Herbivorous::EATER => "plants"
::スコープの作成に使用されます。 2つのモジュールからConstant EATERにアクセスするには、モジュールをスコープして定数に到達する必要があります