Каковы отношения между метаклассом Основы и Производным классом в Ruby?

В Ruby мы могли использовать super в рамках одноэлементного метода для вызова одноэлементного метода соответствующего суперкласса, как следующие шоу кода.

class Base
  def self.class_method
    puts "Base class method"
  end
end

class Derived < Base
  def self.class_method
    puts "Derived class method"
    super
  end
end

Derived.class_method
# Derived class method
# Base class method

Однако я не кажусь, вполне добираются как тот вызов до super в Derived.class_method мог достигнуть Base.class_method. Я принял бы это class_method определяется на их метаклассе, который означает, что их метакласс имеет родительские/дочерние отношения? (Я не могу вполне подтвердить это экспериментами),

Обновление: я задаю этот вопрос, потому что я не забыл видеть где-нибудь существуют некоторые отношения bettwen метакласс основного и производного класса (но я не могу больше находить его). Кроме того, знать как на самом деле super работы, я также хотел бы подтвердить, являются ли эти два метакласса полностью отдельными или нет.

6
задан Josh Lee 26 January 2010 в 07:07
поделиться

3 ответа

Здесь здесь есть четыре класса объектов:

<Class>---class---><Class>
Base               #Base
   ^                  ^
   |                  |
   |                  |
 super              super
   |                  |
   |                  |
<Class>            <Class>
Derived---class--->#Derived

Номенклатура:

  • <...> - это класс каждого объекта.
  • Имя класса на второй строке.
  • Если имя начинается с #, это EIGENCLASS (AKA Singleton Class).
  • Супер указывает на класс класса
  • класса класса.

Когда вы звоните Derived.class_method, Ruby следует правило «вправо, а затем вверх»: сначала перейдите в класс объекта, затем следуйте за цепочкой SuperClass, останавливаясь, когда метод найден:

  • приемник Вызов «Class_Method» получен. Итак, следуйте за цепочкой правом на объект класса извлеченного производным, который является его Eigenclass (#derived).
  • получено не определяет метод, поэтому Ruby следует за цепочкой вверх по цепочке для # Superclass, который является #base.

  • Метод найден там, поэтому Ruby Dispatches Сообщение # Base.class_method

Вы не думаете, что я знал все эти вещи с вершины моей головы, ты? Вот где мой мозг получил всю эту метапудю: MetaProgramming Ruby .

Часть 2. Как сделать «EIGENCLASS» (AKA «Singleton Class») выйти из сокрытия

class Object
  def eigenclass
    class << self
      self
    end
  end
end

Этот метод вернет eigenclass любого объекта. Теперь, как насчет классов? Это тоже объекты.

p Derived.eigenclass               # => #<Class:Derived>
p Derived.eigenclass.superclass    # => #<Class:Base>
p Base.eigenclass                  # => #<Class:Base>

Примечание: выше от Ruby1.9. Когда бежит под рубином 1.8, вы получаете сюрприз:

p Derived.eigenclass.superclass    # => #<Class:Class>
11
ответ дан 8 December 2019 в 12:59
поделиться

Чтобы уточнить и исправить то, что я писал в комментариях относительно того, как Ruby Hides / выдержки Eigenclasses, вот ситуация:

Ruby 1.8:

(1) объект класс # класс ВСЕГДА возвращает первый реальный (неигенкласс или iClass) суперкласс актуальной класса объекта. E.G

o = Object.new
class << o; end
o.class #=> returns Object, even though the _actual_ class is the eigenclass of o

Другими словами, метод класс № класса никогда не вернет eigenclass, он проходит над ними И вместо этого возвращает первый «реальный» класс, он находит в иерархии наследования.

(2) Метод SuperClass класса имеет два случая. Если приемник не является eigenclass, то он просто возвращает суперкласс. Однако, если приемник Eigenclass, то этот метод возвращает фактический (I.e не обязательно реальный) класс приемника.

# case where receiver is a normal class (i.e not an eigenclass)
Module.superclass #=> Object (behaves as expected)

# case where receiver is an eigenclass
class << Module; superclass; end #=> returns Class, this is NOT the superclass

сверху, SuperClass класса # ведет себя, как и ожидалось, в случае нормального класса, но для примера EIGENCLASS он предусматривает, что суперкласс модуля модуля - это класс, который не соответствует действительности. Из этой диаграммы http://banisterfiend.wordpress.com/2008/10/25/the-secret-life-of-singletons/ Мы знаем, что суперкласс собственного модуля на самом деле на самом деле является Eigenclass Объект. Я не уверен, почему Ruby 1.8 имеет это странное поведение.

Ruby 1.9:

(1) Метод класса класс # ведет себя одинаково к версии 1.8.

(2) Метод SuperClass SuperClass Метод SuperClass больше не имеет двух случаев, он теперь лечит наединенные материалы так же, как он относится к нормальным классам и возвращает фактический суперкласс, как и ожидалось.

E.G

class << Module; superclass; end #=> #<Class:Object>
4
ответ дан 8 December 2019 в 12:59
поделиться

Эта диаграмма объясняет отношения: http://banisterfiend.wordpress.com/2008/11/25/a-complete-Ruby-class-diagram/

также, вот некоторые другие сообщения, которые объясняют Больше тонкостей от собственных органов: http://www.klankboomklang.com/2007/10/05/the-metaclass/

http://www.klankboomklang.com/2007/09/21/the-singleton-class/

И вот довольно тяжело, что объясняет больше, чем вы, вероятно, хотели бы знать: http://banisterfiend.wordpress.com/2008/10/25/the-secret-life-of-singletons/

3
ответ дан 8 December 2019 в 12:59
поделиться