Вопрос по ruby – Двойные двоеточия в Ruby (: :) различия в использовании операторов

27

Есть ли разница между

module Foo
  class Engine < Rails::Engine
  end
end

а также

module Foo
  class Engine < ::Rails::Engine
  end
end

Ваш Ответ

2   ответа
49

Константы в Ruby вложены как файлы и каталоги в файловой системе. Таким образом, константы однозначно идентифицируются по их путям.

Чтобы провести аналогию с файловой системой:

::Rails::Engine #is an absolute path to the constant.
# like /Rails/Engine in FS.

Rails::Engine #is a path relative to the current tree level.
# like ./Rails/Engine in FS.

Вот иллюстрация возможной ошибки:

module Foo

  # We may not know about this in real big apps
  module Rails
    class Engine 
    end
  end

  class Engine1 < Rails::Engine
  end

  class Engine2 < ::Rails::Engine
  end
end

Foo::Engine1.superclass
 => Foo::Rails::Engine # not what we want

Foo::Engine2.superclass
 => Rails::Engine # correct
Тонкий момент: еслиRails::Engine определяется за пределамиFoo и это такжеnot определяется внутриFoo затемFoo::Engine1.superclass будетRails::Engine по желанию.
Аналогия с файловой системой великолепна! Спасибо CuriousMind
Хорошая аналогия. Это становится проблематичным, если в разных областях есть модули с одинаковыми именами, поскольку Ruby, похоже, использует первый / ближайший из найденных.
Это было взято из книги "Метапрограммирование Ruby" Паоло Перротта. Очень полезная книга для углубления знаний о Ruby.
Правильно. Так что если вы вызываете Rails :: Engine из модуля, используя имяModule Foo, это может интерпретировать это какFoo::Rails::Engine, Я иногда видел подобные ошибки и должен был добавить дополнительные:: перед включением.
5
Rails::Engine #is a path relative to the current tree level.
# like ./Rails/Engine in FS.

Это не совсем так!

Давайте иметь пример:

module M
  Y = 1
  class M
    Y = 2
    class M
      Y = 3
    end
    class C
      Y = 4
      puts M::Y
    end
  end
end

# => 3

module M
  Y = 1
  class M
    Y = 2
    class C
      Y = 4
      puts M::Y
    end
  end
end

# => 2

module M
  Y = 1
  class M
    Y = 2
    class M
      Y = 4
      puts M::Y
    end
  end
end

# => 4

Поэтому, когда вы говорите, что M :: Y ruby ищет наиболее близкое определение, независимо от того, находится оно внутри текущей или внешней области или внешней внешней области и т. Д.

какой это рубин? На 2.2.4 я получаю 3, 3 и 4 и множество «констант верхнего уровня, на которые уже ссылались предупреждения»

Похожие вопросы