Руби Коанс: явное определение области действия для определения класса, часть 2 - PullRequest
20 голосов
/ 29 марта 2011

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

  1. Ограждающая область
  2. Любые внешние области действия (повторять до достижения верхнего уровня)
  3. Входящие в комплект модули
  4. суперкласса (ов)
  5. Object
  6. Kernel

Итак, чтобы уточнить, на каком шаге (1-6) находится значение для константы LEGS, найденное для legs_in_oyster? Это из суперкласса Animal? Является ли область действия класса MyAnimals игнорируемой, поскольку она не считается охватывающей областью действия? Это связано с явным определением класса MyAnimals::Oyster?

Спасибо! Просто пытаюсь понять. Вот код:

 class Animal
   LEGS = 4
   def legs_in_animal
     LEGS
   end

   class NestedAnimal
     def legs_in_nested_animal
       LEGS
     end
   end
 end

 def test_nested_classes_inherit_constants_from_enclosing_classes
   assert_equal 4, Animal::NestedAnimal.new.legs_in_nested_animal
 end

 # ------------------------------------------------------------------

 class MyAnimals
   LEGS = 2

   class Bird < Animal
     def legs_in_bird
       LEGS
     end
   end
 end

 def test_who_wins_with_both_nested_and_inherited_constants
   assert_equal 2, MyAnimals::Bird.new.legs_in_bird
 end

 # QUESTION: Which has precedence: The constant in the lexical scope,
 # or the constant from the inheritance heirarachy?

 # ------------------------------------------------------------------

 class MyAnimals::Oyster < Animal
   def legs_in_oyster
     LEGS
   end
 end

 def test_who_wins_with_explicit_scoping_on_class_definition
   assert_equal 4, MyAnimals::Oyster.new.legs_in_oyster
 end

 # QUESTION: Now Which has precedence: The constant in the lexical
 # scope, or the constant from the inheritance heirarachy?  Why is it
 # different than the previous answer?
 end

1 Ответ

32 голосов
/ 30 марта 2011

Я просто размышлял над тем же вопросом из того же самого коана. Я не специалист в области определения объема работ, но следующее простое объяснение имело для меня большой смысл, и, возможно, оно также поможет вам.

Когда вы определяете MyAnimals::Oyster, вы все еще находитесь в глобальной области видимости, поэтому ruby ​​не знает о значении LEGS, установленном в 2 в MyAnimals, потому что вы на самом деле никогда не находитесь в области действия MyAnimals (немного противоречащий).

Однако все было бы иначе, если бы вы определили Oyster так:

class MyAnimals
  class Oyster < Animal
    def legs_in_oyster
      LEGS # => 2
    end
  end
end

Разница в том, что в приведенном выше коде к тому времени, когда вы определяете Oyster, вы попадаете в область действия MyAnimals, поэтому ruby ​​знает, что LEGS относится к MyAnimals::LEGS (2), а не Animal::LEGS (4).

К вашему сведению, я получил это представление по следующему URL (указанному в вопросе, на который вы ссылались):

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...