Что такое двойная двоеточие Ruby `::`? - PullRequest
394 голосов
/ 10 июня 2010

Что это за двойное двоеточие ::?Например, Foo::Bar.

Я нашел определение :

:: - это унарный оператор, который позволяет: определять константы, методы экземпляра и методы классавнутри класса или модуля, к которому можно получить доступ из любого места за пределами класса или модуля.

Что хорошего в области (приватной, защищенной), если вы можете просто использовать ::, чтобы выставить что-нибудь?

Ответы [ 10 ]

353 голосов
/ 10 июня 2010

:: в основном оператор разрешения пространства имен.Это позволяет вам получать доступ к элементам в модулях или элементам уровня класса в классах.Например, допустим, у вас была такая настройка:

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

Вы можете получить доступ к CONSTANT извне модуля как SomeModule::InnerModule::MyClass::CONSTANT.

Это не влияет на методы экземпляра, определенные в классе, поскольку вы обращаетесь к тем с другим синтаксисом (точка .).

Соответствующее примечание: Если вы хотите вернуться к пространству имен верхнего уровня, сделайте это: :: SomeModule - BenjaminОукс

104 голосов
/ 16 марта 2011

Этот простой пример иллюстрирует это:

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

70 голосов
/ 10 июня 2010

:: Позволяет получить доступ к константе, модулю или классу, определенному внутри другого класса или модуля. Он используется для предоставления пространств имен, чтобы имена методов и классов не конфликтовали с другими классами разных авторов.

Когда вы видите ActiveRecord::Base в Rails, это означает, что в Rails есть что-то вроде

module ActiveRecord
  class Base
  end
end

т.е. класс с именем Base внутри модуля ActiveRecord, который затем называется ActiveRecord::Base (вы можете найти его в источнике Rails в activerecord-n.n.n / lib / active_record / base.rb)

Обычно используется :: для доступа к константам, определенным в модулях, например

module Math
  PI = 3.141 # ...
end

puts Math::PI

Оператор :: не позволяет вам игнорировать видимость методов, помеченных как закрытые или защищенные.

23 голосов
/ 10 июня 2010

Что хорошего в области видимости (частной, защищенной), если вы можете просто использовать ::, чтобы выставить что-нибудь?

В Ruby все открыто и все может быть изменено из любого места.

Если вас беспокоит тот факт, что классы могут быть изменены вне «определения класса», то, вероятно, Ruby не для вас.

С другой стороны, если вы 'разочарован тем, что классы Java заблокированы, тогда Ruby, вероятно, то, что вы ищете.

11 голосов
/ 10 июня 2010

Нет, это не для доступа к каждому методу, это оператор «разрешения», то есть вы используете его для разрешения области (или местоположения, которую вы можете сказать) постоянного / статического символа.

Например, в первой строке Rails использует его для поиска базового класса внутри ActiveRecord.Module, во втором - для поиска метода класса (статического) класса Routes и т. Д., И т. Д.

Он не используется для показа чего-либо, он используется для "локализации" вещей вокруг ваших областей.

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

8 голосов
/ 09 июня 2017

Добавляя к предыдущим ответам, Ruby может использовать :: для доступа к методам экземпляра. Все следующие действительны:

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

В соответствии с лучшими практиками, я считаю, что рекомендуется только последний.

4 голосов
/ 10 июня 2010

Все дело в том, чтобы предотвратить столкновение определений с другим кодом, связанным с вашим проектом.Это означает, что вы можете держать вещи отдельно.

Например, в вашем коде может быть один метод с именем «run», и вы все равно сможете вызывать его, а не метод «run», который был определен в какой-то другой библиотеке, с которой вы связаны.

3 голосов
/ 06 марта 2019

Удивительно, но все 10 ответов здесь говорят об одном и том же.'::' является оператором разрешения пространства имен, и да, это правда.Но есть один момент, который вы должны понять, об операторе разрешения пространства имен, когда дело доходит до алгоритма постоянного поиска .Как подчеркивает Матц в своей книге «Язык программирования 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 будут ссылаться на константу PIопределено в модуле B. Теперь, если модуль B не определил PI, тогда экземпляры F будут ссылаться на константу PI, определенную в суперклассе E.

Но что, если бы мы использовали «::» вместо вложенностимодули?Получим ли мы такой же результат?Нет!

При использовании оператора разрешения пространства имен при определении вложенных модулей вложенные модули и классы больше не попадают в лексическую область своих внешних модулей.Как вы можете видеть ниже, PI, определенный в A :: B, не входит в лексическую область A :: B :: C :: D, и поэтому мы получаем неинициализированную константу при попытке обратиться к PI в методе экземпляра get_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 голосов
/ 10 августа 2013

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
2 голосов
/ 08 апреля 2015
module Amimal
      module Herbivorous
            EATER="plants" 
      end
end

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

:: Используется для создания области.Чтобы получить доступ к Constant EATER из 2-х модулей, нам нужно настроить модули так, чтобы они доходили до постоянной

...