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

Классы Ruby в классах (или модулях в модулях)

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

class Outerclass
  def foobar
    puts "FOOBAR"
  end

  class Innerclass   
    def barfoo
      puts "BARFOO"
    end
  end
end

Вот код, который я запускал в IRB, чтобы понять это концептуально:

oc = Outerclass.new # => #<Outerclass:0x00000100a46478>

Outerclass.instance_methods(false) # => [:foobar]

ic = Outerclass::Innerclass.new # => #<Outerclass::Innerclass:0x00000100a0b120>

ic = Outerclass::Innerclass.instance_methods(false) # => [:barfoo]

Вот мои вопросы:

  • Когда интерпретатор ruby ​​впервые встречает мой код определения класса выше, он просматривает методы, которые я написал, и где-нибудь их где-то храню? Я знаю, что метод экземпляра "foobar" фактически не запускается, поскольку в определении Outerclass нет вызова.

  • Устранив первый вопрос, как насчет того, когда Ruby сталкивается с классом Innerclass? Что здесь происходит?

  • В общем, каковы некоторые причины, по которым вы хотели бы иметь классы внутри классов? Есть ли какие-либо преимущества для этого?

  • Означает ли экземпляр Outerclass что-либо о классе Innerclass?

  • Означает ли экземпляр Innerclass что-либо о классе Outerclass?

Оцените любую помощь, которую вы можете предоставить!

4b9b3361

Ответ 1

Когда интерпретатор просматривает этот файл, он назначает классы следующим образом:

OuterClass = Class.new do 
  def foobar
    puts "FOOBAR"
  end

  InnerClass = Class.new do   
    def barfoo
      puts "BARFOO"
    end
  end
end

Итак, когда Ruby встречает вложенный класс, он присваивает ему константу InnerClass, которой присваивается константа OuterClass. Они не имеют никакого отношения друг к другу.

InnerClass не имеет наследования OuterClass:

  InnerClass.ancestors
  => [InnerClass, Object, Kernel, BasicObject]

Когда вы вызываете константу OuterClass::InnerClass, вы ссылаетесь на константу InnerClass, которая именуется под константой OuterClass, которая равна назначению ей инструкции Class.new.

Хорошая книга, чтобы прочитать об этом - "Метапрограммирование Рубина". Он посвящен деталям классов, синглтонов, модулей и т.д.