Я изучаю рубиновую объектную модель и имею некоторые вопросы. Я понимаю идею, что объект только хранит переменные экземпляра, и методы хранятся в классе, на который объект имеет ссылку. Я также понимаю идею 'сам' - каково это, как это изменяется и т.д.
Однако то, что я не понимаю, является понятием, что 'классы являются объектами'. Где-нибудь существует ли хорошее, интуитивное объяснение?
(BTW: я использую Объектную модель Ruby и Metaprogramming и Metaprogramming Ruby как мои два ресурса. Если бы кто-либо может предложить что-то еще, которое было бы полезно.)
Спасибо.
Вот мой выстрел в одного.
В Ruby классы - это объекты. Обычно у них есть класс Класс
. Например, рассмотрим класс Foo
.
class Foo
end
Несомненно, вы видели это раньше, и это не так уж и интересно. Но мы также могли бы определить Foo
следующим образом:
Foo = Class.new
Так же, как вы создали бы новый Foo
, вызвав Foo.new
, вы можете создать новый Класс
путем вызова Class.new
. Затем вы присваиваете этому классу имя Foo
, присваивая его, как и любой другой переменной. Это все, что нужно сделать.
Посмотрите эту статью, она может оказаться вам полезной:
Объектная модель Ruby - структура и семантика
Лично я много узнал об объектной модели Ruby, прочитав о Smalltalk (например, в документации Squeak ). И в зависимости от того, насколько свободно вы владеете C, источники МРТ вполне доступны и дают наиболее однозначные ответы.
Это означает именно то, что звучит - классы являются объектами. В частности, они являются экземплярами класса Class
, который сам является подклассом класса Module
, который в свою очередь является подклассом Object
, как и любой другой класс в Ruby. Как и любой другой объект в Ruby, класс может отвечать на сообщения, иметь свои собственные переменные экземпляра и т.д.
В качестве практического примера возьмем private
.
class Person
attr_accessor :name, :height
private
attr_accessor :weight
end
Это дает экземплярам Person публичные методы для доступа к имени и росту человека, но методы доступа к весу человека являются приватными. НО - вместо того, чтобы быть ключевым словом, как в большинстве языков, private
является обычным методом класса Module. Если бы мы захотели, мы могли бы переопределить его, чтобы он делал что-то другое для конкретной иерархии классов.
class RichardStallman
def self.private(*args)
puts "NO! INFORMATION WAS MEANT TO BE FREE!"
end
end
Понятие «классы есть объекты» (насколько я понимаю) подразумевает, что все, что вы можете делать с объектом, вы можете делать с помощью класса.
Это отличается от других языков программирования, где класс и определение класса являются специальными артефактами, отличными от объектов и часто недоступными для среды выполнения.
Например, в Ruby вы можете изменять любой объект во время выполнения, поскольку классы также являются объектами, вы можете изменять сам класс и добавлять методы во время выполнения, удалять методы или добавлять и удалять атрибуты во время выполнения.
Например:
$ irb
>> x = Object.new
=> #<Object:0x1011ce560>
>> x.to_s
=> "#<Object:0x1011ce560>"
>> undef to_s
=> nil
>> x.to_s
NoMethodError: undefined method `to_s' for #<Object:0x1011ce560>
from (irb):4
>>
Это невозможно на других языках программирования, где проводится различие между объектами и классами.
примечание: вероятно, вам следует понять основные концепции Ruby, прежде чем переходить к метапрограммированию, поскольку это может сбивать с толку то, что я сделал бы.
Если подумать, то совершенно логично, что new
- это функция, верно? Функция, которая создает и возвращает новый объект. (В отличие от большинства других языков, где new
является каким-то оператором или конструкцией языка.)
Если пойти дальше, то еще более логичным для этой функции new
является то, что она должна быть методом, если мы говорим об ОО-языке. Чей метод? Метод объекта, только немного другого типа объекта, который мы можем назвать "классом".
Итак, если смотреть с этой точки зрения, классы - это просто особые виды объектов, объекты, которые, среди прочих особенностей, имеют метод new
и умеют создавать другие объекты на основе своего образа.