Ruby'nin çift sütunu `::` nedir?


427

Bu çift kolon ::nedir? Örn Foo::Bar.

Bir tanım buldum :

Bu ::, bir sınıf veya modül içinde tanımlanan sabitlere, örnek yöntemlere ve sınıf yöntemlerine sınıf veya modül dışındaki herhangi bir yerden erişilmesine olanak tanıyan tekli bir işleçtir.

Bir ::şeyi ortaya çıkarmak için kullanabiliyorsanız kapsam (özel, korunan) ne işe yarar ?


175
Gelecekteki Google çalışanlarının yararı için, bir simge aramaya çalışıyorsanız symbolhound.com'u
Andrew Grimm



6
Seni korusun, @ AndrewGrimm. Bu hafta gördüğüm en iyi şey bu.
abeger

Yanıtlar:


381

::temel olarak bir ad alanı çözümleme operatörüdür. Modüllerdeki öğelere veya sınıflardaki sınıf düzeyi öğelere erişmenizi sağlar. Örneğin, şu kurulumu yaptığınızı varsayalım:

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

CONSTANTModül dışından olarak erişebilirsiniz SomeModule::InnerModule::MyClass::CONSTANT.

Farklı bir sözdizimine (nokta .) sahip olanlara eriştiğiniz için, sınıfta tanımlanan örnek yöntemlerini etkilemez .

İlgili not: Üst düzey ad alanına geri dönmek istiyorsanız, şunu yapın: :: SomeModule - Benjamin Oakes


5
Örneğin C # 'da evet. Öte yandan C ++ (ve Ruby) ::gibi ad alanı çözünürlüğü için kullanınstd::cout << "Hello World!";
Jerry Fernholz

142
İlgili not: Üst düzey ad alanına geri dönmek istiyorsanız, şunu yapın: ::SomeModule
Benjamin Oakes

5
@Benjamin Başka bir modülün içinde bir SomeModule yoksa ve bunun yerine üst düzey olanı almak istemezsem, önde gelen iki nokta üst üste işaretler ima edilir, doğru mu?
Jo Liss

7
@ Evet. Üst düzey ad alanındaki bir sabite veya başka bir modülde aynı ada sahip bir sabite başvurduğunuzdan emin olmak yararlı olabilir (örn. :: SomeOtherModule :: ClassMethods).
Benjamin Oakes

2
Bu, C ++ 'nın kapsam operandına çok benziyor
lkahtz

111

Bu basit örnek bunu göstermektedir:

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

Alındığı http://www.tutorialspoint.com/ruby/ruby_operators.htm


uyarıya sebep olan da budur. Uyarıyı atlatmanın bir yolu var mı?
NullVoxPopuli

3
@NullVoxPopuli Genel olarak sabitleri değiştirmek gerçekten kötü bir şeydir, ancak örneğin kötü yazılmış bir değerli taştaki bir sabiti değiştirmek ve çatallamak istemiyorsanız, tanımlayan modüle .send (: remove_const) kullanılarak yapılabilir. sonra sabiti yeniden tanımlıyor.
BookOfGreg

71

::Başka bir sınıf veya modül içinde tanımlanan bir sabite, modüle veya sınıfa erişmenizi sağlar. Ad alanları sağlamak için kullanılır, böylece yöntem ve sınıf adları farklı yazarların diğer sınıflarıyla çakışmaz.

Gördüğünde ActiveRecord::BaseRails'te , Rails'in

module ActiveRecord
  class Base
  end
end

yani Base modül olarakActiveRecord ve daha sonra atıfta bulunulanActiveRecord::Base (bunu activerecord-nnn / lib / active_record / base.rb dosyasındaki Rails kaynağında bulabilirsiniz)

:: 'nin yaygın kullanımı, modüllerde tanımlanan sabitlere örn.

module Math
  PI = 3.141 # ...
end

puts Math::PI

::Yöntemlerin baypas görünürlük sizi izin vermez operatör özel veya korumalı işaretli.


7
Öyleyse, varsa class MyClass < ActiveRecord::Base, bu MyClass'ın ActiveRecord modülünün içindeki herhangi bir şeyi değil, yalnızca sınıf tabanından yöntemleri miras aldığı anlamına mı geliyor?
Charlie Parker

2
Neden "." Kullanmak yerine bu ad alanı çözünürlüğü için özel çift sütunu kullanmalısınız. bunun için mi? Bağlam ve büyük harf kullanımı "." Kelimesini kullanıyor olsak bile anlam karışıklığını önleyecektir, değil mi?
Jonah

3
@Jonah belirsiz olduğu bazı durumlar var. örneğin düşünün class Foo; Baz = 42; def self.Baz; "Baz method!"; end; end(tamamen geçerli) Foo::Baz # => 42ve Foo.Baz # => "Baz method!". Not Foo::Baz()(parantez ile birlikte) da olsa yöntemini çağırır.
mikej

3
Yani kullanım örneği, sınıf sabitine sahip olma yeteneğini ve tam olarak aynı ada sahip bir sınıf yöntemini çözer mi? Bu özellik lehine güçlü bir argüman gibi görünmüyor. Şahsen ben bu yeteneği kaybetmeyi tercih ederim (yine de bela gibi görünüyor), çift kolonunu kaybedip "." ad alanı için de ... Belki çözdüğü ek kullanım durumları var?
Jonah

26

:: 'yi herhangi bir şeyi ortaya çıkarmak için kullanabiliyorsanız kapsam (özel, korumalı) ne işe yarar?

Ruby'de her şey ortaya çıkar ve her şey başka bir yerden değiştirilebilir.

Sınıfların "sınıf tanımı" dışından değiştirilebileceğinden endişe ediyorsanız, Ruby muhtemelen sizin için değildir.

Öte yandan, Java'nın sınıflarının kilitli olmasından rahatsız olursanız, Ruby muhtemelen aradığınız şeydir.


1
Bazı rubyistlerin örnek değişkenlerinin açıkta kalmadığını, attr_accessorsadece değişkeni değiştiren yöntemleri bile yaptığını duydum . (Sonra tekrar var instance_eval)
Andrew Grimm

4
Doğru, var instance_eval. Ama instance_variable_getve de var instance_variable_set. Ruby kısıtlamalar için çok dinamik.
yfeldblum

12

Önceki yanıtlara ek olarak, ::örnek yöntemlerine erişmek için Ruby kullanılır. Aşağıdakilerin tümü geçerlidir:

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

En iyi uygulamalara göre sadece sonuncunun önerildiğine inanıyorum.


11

Hayır, her yönteme erişmek değildir, bir "çözüm" operatörüdür, yani sabit / statik bir sembolün kapsamını (veya söyleyebileceğiniz konumu) çözmek için kullanırsınız.

Örneğin, çizginizin ilk bölümünde, Rails bunu ActiveRecord.Module içindeki Base sınıfını bulmak için kullanır, ikincisinde ise Routes sınıfının sınıf yöntemini (statik) vb. Bulmak için kullanılır.

Hiçbir şeyi ortaya çıkarmak için kullanılmaz, kapsamlarınızın etrafındaki şeyleri "bulmak" için kullanılır.

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


"(statik)" ile mi demek istediniz "(draw)"?!?
Meltemi

8

Şaşırtıcı bir şekilde, buradaki 10 cevabın hepsi aynı şeyi söylüyor. '::' bir ad alanı çözünürlük operatörüdür ve evet doğrudur. Ancak, sabit arama algoritması söz konusu olduğunda, ad alanı çözünürlük operatörü hakkında fark etmeniz gereken bir şey var . Matz 'Ruby Programlama Dili' adlı kitabında betimlediği gibi, sürekli aramanın birden fazla adımı vardır. İlk olarak, söz konusu sabitin atıfta bulunduğu sözcüksel kapsamda bir sabiti arar . Sabit noktayı sözlük kapsamı içinde bulamazsa, kalıtım hiyerarşisini arar . Bu sürekli arama algoritması nedeniyle, aşağıda beklenen sonuçları elde ediyoruz:

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'den miras alırken, B modülü F'nin sözcüksel kapsamı içindedir. Sonuç olarak, F örnekleri B modülünde tanımlanan sabit PI'ye atıfta bulunacaktır. Şimdi B modülü PI tanımlamıyorsa, F örnekleri PI'ye atıfta bulunacaktır. E üst sınıfında tanımlanan sabit.

Peki ya modül yerleştirme yerine '::' kullanacaksak? Aynı sonucu alır mıydık? Hayır!

Yuvalanmış modülleri tanımlarken ad alanı çözümleme işlecini kullanarak, yuvalanmış modüller ve sınıflar artık dış modüllerinin sözcüksel kapsamı içinde değildir. Aşağıda görebileceğiniz gibi, A :: B'de tanımlanan PI A :: B :: C :: D'nin sözcüksel kapsamı içinde değildir ve bu nedenle get_pi örnek yönteminde PI'ye başvurmaya çalışırken başlatılmamış sabit alırız:

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

Her şey, tanımların projenize bağlı diğer kodlarla çakışmasını önlemekle ilgilidir. Bu, işleri ayrı tutabileceğiniz anlamına gelir.

Örneğin, kodunuzda "run" adlı bir yönteminiz olabilir ve bağladığınız diğer kitaplıklarda tanımlanan "run" yöntemi yerine yönteminizi çağırabilirsiniz.


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

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

:: Bir kapsam oluşturmak için kullanılır. Constant EATER'a 2 modülden erişmek için, modülleri sabite kadar ulaşacak şekilde kapsamamız gerekir


3

Ruby on rails ::ad alanı çözünürlüğü için kullanır .

class User < ActiveRecord::Base

  VIDEOS_COUNT = 10
  Languages = { "English" => "en", "Spanish" => "es", "Mandarin Chinese" => "cn"}

end

Kullanmak için:

User::VIDEOS_COUNT
User::Languages
User::Languages.values_at("Spanish") => "en"

Ayrıca, diğer kullanım alanları: İç içe yollar kullanılırken

OmniauthCallbacksController , kullanıcılar altında tanımlanır.

Ve şu şekilde yönlendirilir:

devise_for :users, controllers: {omniauth_callbacks: "users/omniauth_callbacks"}


class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController

end
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.