Ruby의 이중 콜론`::`은 무엇입니까?


427

이 이중 콜론은 무엇입니까 ::? 예 Foo::Bar.

정의를 찾았습니다 .

::허용 단항 연산자 : 클래스 또는 모듈 내에 정의 된 상수, 인스턴스 메소드와 클래스 메소드는 클래스 또는 모듈의 외부를 통해 액세스된다.

무엇 ::이든 노출 하기 위해 사용할 수 있다면 스코프 (개인, 보호) 는 무엇입니까?


175
미래 Google 직원들의 이익을 위해 심볼을 검색하려는 경우 symbolhound.com을
Andrew Grimm



6
@AndrewGrimm, 당신을 축복하십시오. 이것이 이번 주에 본 최고의 것입니다.
abeger

답변:


381

::기본적으로 네임 스페이스 확인 연산자입니다. 모듈의 항목 또는 클래스의 클래스 레벨 항목에 액세스 할 수 있습니다. 예를 들어, 다음과 같이 설정했다고 가정하십시오.

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

CONSTANT모듈 외부에서로 액세스 할 수 있습니다 SomeModule::InnerModule::MyClass::CONSTANT.

다른 구문 (dot .)으로 액세스하기 때문에 클래스에 정의 된 인스턴스 메소드에는 영향을 미치지 않습니다 .

관련 참고 사항 : 최상위 네임 스페이스로 돌아가려면 다음과 같이하십시오. :: SomeModule – Benjamin Oakes


5
예를 들어 C #에서는 그렇습니다. 반면에 C ++ (및 Ruby) ::은 네임 스페이스 확인에 사용됩니다.std::cout << "Hello World!";
Jerry Fernholz

142
관련 참고 사항 : 최상위 네임 스페이스로 돌아가려면 다음과 같이하십시오. ::SomeModule
Benjamin Oakes

5
@ Benjamin 다른 모듈 내에 SomeModule이없고 최상위 모듈을 대신 사용하고 싶지 않다면 선행 콜론이 암시됩니다.
Jo Liss

7
@ 조 예. 최상위 네임 스페이스의 상수 나 다른 모듈에서 같은 이름의 상수 (예 : :: SomeOtherModule :: ClassMethods)를 참조하려는 경우 도움이 될 수 있습니다.
Benjamin Oakes

2
이것은 C ++의 범위 피연산자와 매우 유사합니다
lkahtz

111

이 간단한 예는 다음을 보여줍니다.

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

http://www.tutorialspoint.com/ruby/ruby_operators.htm 에서 가져옴


이것이 경고의 원인입니다. 경고를 피할 수있는 방법이 있습니까?
NullVoxPopuli

3
@NullVoxPopuli 일반적으로 상수를 수정하는 것은 실제로 나쁜 일이지만, 예를 들어 잘못 작성된 gem의 상수를 수정하고 포크하지 않으려는 경우 .send (: remove_const) 를 사용하여 정의하는 모듈에 수행 할 수 있습니다 그런 다음 상수를 재정의하십시오.
BookOfGreg

71

::다른 클래스 또는 모듈 내에 정의 된 상수, 모듈 또는 클래스에 액세스 할 수 있습니다. 메소드와 클래스 이름이 다른 작성자의 다른 클래스와 충돌하지 않도록 네임 스페이스를 제공하는 데 사용됩니다.

ActiveRecord::BaseRails에서 볼 때 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

::방법의 바이 패스 가시성을 허용하지 않습니다 운영자는 개인 또는 보호 표시했다.


7
그렇다면 하나는 class MyClass < ActiveRecord::BaseMyClass가 ActiveRecord 모듈 내부의 클래스가 아닌 클래스 기반의 메소드 만 상속한다는 것을 의미합니까?
Charlie Parker

2
"."대신이 네임 스페이스 확인에 특수 이중 콜론을 사용하는 이유 이것도? 문맥과 대문자는 "."을 사용하더라도 의미의 혼동을 막을 것입니다.
요나

3
@Jonah는 모호한 경우가 있습니다. 예를 들어 class Foo; Baz = 42; def self.Baz; "Baz method!"; end; end(완전히 유효한) Foo::Baz # => 42및을 고려하십시오 Foo.Baz # => "Baz method!". 그 주 Foo::Baz()(괄호)도 비록 메소드를 호출합니다.
mikej

3
따라서 유스 케이스는 클래스 상수를 갖는 기능과 이름이 정확히 같은 클래스 메소드를 해결합니까? 그것은 그 기능에 찬성하는 강력한 주장처럼 보이지 않습니다. 개인적으로 나는 그 능력을 잃어 버리고 (어쨌든 문제가있는 것처럼 보임) 이중 콜론을 잃고 "." 네임 스페이스도 .... 어쩌면 추가적인 유스 케이스가 있습니까?
요나

26

::를 사용하여 아무것도 노출시킬 수 있다면 스코프 (개인, 보호)는 무엇입니까?

루비에서는 모든 것이 노출되고 다른 곳에서 모든 것을 수정할 수 있습니다.

클래스가 "클래스 정의"외부에서 변경 될 수 있다는 사실이 걱정된다면 Ruby가 적합하지 않을 것입니다.

반면에, Java의 클래스가 잠겨있어 좌절한다면 Ruby가 아마도 당신이 찾고있는 것일 것입니다.


1
일부 루비 스트들은 인스턴스 변수가 노출되지 않으며 attr_accessor단순히 변수를 수정하는 메소드를 만드는 것이라고 들었습니다 . (그런데 다시있다 instance_eval)
Andrew Grimm

4
맞습니다 instance_eval. 뿐만 아니라 거기에 instance_variable_getinstance_variable_set. 루비는 제약 조건에 비해 너무 역동적입니다.
yfeldblum 2016 년

12

이전 답변에 추가하여 ::인스턴스 메소드에 액세스 하는 데 유효한 Ruby 입니다. 다음은 모두 유효합니다.

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

모범 사례에 따라 마지막 것만 권장한다고 생각합니다.


11

아니요, 모든 방법에 액세스하는 것이 아니라 "해상도"연산자입니다. 즉, 상수 / 정적 기호의 범위 (또는 말할 수있는 위치)를 해결하는 데 사용합니다.

예를 들어 첫 번째 줄에서 Rails는 ActiveRecord.Module 내에서 Base 클래스를 찾는 데 사용하고 두 번째 줄에서는 Routes 클래스 등의 클래스 메서드 (정적)를 찾는 데 사용됩니다.

그것은 당신의 스코프 주위에 물건을 위치시키는 데 사용되는 것을 드러내는 데 사용되지 않습니다.

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


"(정적)"은 "(draw)"를 의미합니까?!?
Meltemi

8

놀랍게도, 여기에있는 10 개의 답변은 모두 같은 것을 말합니다. '::'는 네임 스페이스 확인 연산자이며, 그렇습니다. 그러나 상수 조회 알고리즘과 관련 하여 네임 스페이스 확인 연산자에 대해 알아야 할 사항이 하나 있습니다 . Matz가 그의 책 'The Ruby Programming Language'에서 묘사 한 것처럼, 지속적인 검색은 여러 단계를 거칩니다. 먼저, 상수가 참조되는 어휘 범위 에서 상수를 검색합니다 . 어휘 범위 내에서 상수를 찾지 못하면 상속 계층 구조 를 검색합니다 . 이 상수 조회 알고리즘으로 인해 아래 예상 결과를 얻습니다.

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

4

정의가 프로젝트에 연결된 다른 코드와 충돌하는 것을 막는 것입니다. 그것은 당신이 물건을 분리하여 유지할 수 있음을 의미합니다.

예를 들어 코드에 "run"이라는 하나의 메소드가있을 수 있으며 링크 된 다른 라이브러리에 정의 된 "run"메소드가 아닌 메소드를 계속 호출 할 수 있습니다.


3
module Amimal
      module Herbivorous
            EATER="plants" 
      end
end

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

:: 범위를 만드는 데 사용됩니다. 2 개의 모듈에서 Constant EATER에 액세스하려면 상수에 도달하도록 모듈의 범위를 지정해야합니다.


3

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.