web-dev-qa-db-ja.com

Rubyのダブルコロン `::`とは何ですか?

このダブルコロン::とは何ですか?例えば。 Foo::Bar

定義 が見つかりました:

::は単項演算子であり、クラスまたはモジュール内で定義された定数、インスタンスメソッド、およびクラスメソッドに、クラスまたはモジュールの外部からアクセスできます。

::を使用して何かを公開できる場合、スコープ(プライベート、保護)はどのようなものですか?

392
Meltemi

::は、基本的に名前空間解決演算子です。モジュール内のアイテム、またはクラス内のクラスレベルのアイテムにアクセスできます。たとえば、次の設定があったとしましょう:

module SomeModule
    module InnerModule
        class MyClass
            CONSTANT = 4
        end
    end
end

SomeModule::InnerModule::MyClass::CONSTANTとしてモジュールの外部からCONSTANTにアクセスできます。

異なる構文(ドット.)でアクセスするため、クラスで定義されたインスタンスメソッドには影響しません。

関連するメモ:最上位の名前空間に戻りたい場合は、これを実行します。:: SomeModule – Benjamin Oakes

351
mipadi

次の簡単な例で説明します。

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

http://www.tutorialspoint.com/Ruby/ruby_operators.htm から取得

103
Nader

::別のクラスまたはモジュール内で定義された定数、モジュール、またはクラスにアクセスできます。メソッドおよびクラス名が異なる作成者による他のクラスと競合しないように、名前空間を提供するために使用されます。

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とマークされたメソッドの可視性をバイパスできません。

70
mikej

::を使用して何かを公開できる場合、スコープ(プライベート、保護)はどのような利点がありますか?

Rubyでは、すべてが公開されており、他のどこからでもすべてを変更できます。

「クラス定義」の外部からクラスを変更できるという事実を心配しているなら、Rubyはおそらくあなたには向いていないでしょう。

一方、Javaのクラスがロックされていることに不満を感じているなら、Rubyがおそらくあなたが探しているものです。

23
yfeldblum

いいえ、すべてのメソッドにアクセスするのではなく、「解決」演算子です。つまり、これを使用して、定数/静的シンボルのスコープ(または言うことができる場所)を解決します。

たとえば、最初の行では、RailsはActiveRecord.Module内でBaseクラスを見つけるためにそれを使用し、2番目の行ではRoutesクラスなどのクラスメソッド(静的)を見つけるために使用されます。

何かを公開するために使用されるのではなく、スコープの周りにあるものを「見つける」ために使用されます。

http://en.wikipedia.org/wiki/Scope_resolution_operator

11
Francisco Soto

以前の回答に加えて、::を使用してインスタンスメソッドにアクセスすることは有効なRubyです。以下はすべて有効です。

MyClass::new::instance_method
MyClass::new.instance_method
MyClass.new::instance_method
MyClass.new.instance_method

ベストプラクティスに従って、最後の1つだけが推奨されると信じています。

8
Yuri Ghensev

定義は、プロジェクトにリンクされている他のコードと衝突しないようにすることです。それはあなたが物事を別々に保つことができることを意味します。

たとえば、コード内で「run」というメソッドを1つ持つことができますが、リンクした他のライブラリで定義された「run」メソッドではなく、メソッドを呼び出すことができます。

4
Mongus Pong

驚くべきことに、ここでの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
3
Donato

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
3
Pankhuri
module Amimal
      module Herbivorous
            EATER="plants" 
      end
end

Amimal::Herbivorous::EATER => "plants"

::スコープの作成に使用されます。 2つのモジュールからConstant EATERにアクセスするには、モジュールをスコープして定数に到達する必要があります

2