Подтвердить что ты не робот

Ruby Koans: явное определение области определения класса 2

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

  • Прилагаемый объем
  • Любые внешние области (повторяются до достижения верхнего уровня)
  • Включенные модули
  • суперкласса (ов)
  • Объект
  • 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
4b9b3361

Ответ 1

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

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

Однако все было бы иначе, если бы вы определили Oyster следующим образом:

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

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

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