понедельник, 28 февраля 2011 г.

Классы — это объекты

Кто изучает Ruby, знает, что в нем все сущности — объекты, но порой не догадывается насколько. Так вот, классы в Ruby это тоже объекты.
В Ruby классы — это объекты являющиеся экземплярами класса Class.


Напоминание из ООП


Класс — это тип, описывающий устройство объектов.
Объект — сущность в адресном пространстве ЭВМ, появляющаяся при создании экземпляра класса.

В дальнейшем для удобства чтения иногда буду употреблять термин экземпляр (instance) для объекта
и термин тип для класса.

Свойства класса нужно где-то хранить.


Так как каждый описываемый класс имет различные свойства и выполняемый код, то их нужно где-то хранить. А где Ruby хранит данные? Правильно, в объектах. И логично, что у объектов, описывающих какой-то класс, должен быть свой тип. Так и есть, тип (класс) объектов описывающих классы — Class.

Анонимный класс

Механизм создания класса в Ruby можно понять на таком непопулярном способе.

myklass = Class.new do
  def test
    puts "TEST"
  end
  def self.ctest
    puts "CLASS TEST"
  end
end

myklass         # => #<Class:0xb6f3e768>       
myklass.class   # => Class
myklass.name    # => ""
myklass.ctest   # => "CLASS TEST"


Мы сейчас создали абсолютно нормальный, но анонимный класс (метод name возвращает пустую строку) и
поместили его в переменную myklass. Что такое myklass? Это объект, в котором хранится описание нашего класса, класс этого объекта — Class.

Наш анонимный класс, все его методы и переменные существует только в объекте myklass.

Экземпляр анонимного класса

Экземпляр анонимного класса (то есть его объект) создается также как и для любого другого:

m = myklass.new

m.test            # => 'TEST'
m.class           # => #<Class:0xb6f3e768>
m.class==myklass  # => true


Наследование анонимного класса

Наследовать анонимный класс можно точно так же, как и неанонимный.

class MyKlass2 < myklass
  #  ...
end

MyKlass2.superclass == myklass  #  => true

# или опять анонимно:

mk2 = Class.new myklass do
  # ..
end

mk2.superclass == myklass
mk2.name          # => ""


Назови меня по имени

Тут немного магии от Ruby. Имя у класса появляется в тот момент, когда объект, описывающий класс, присваивается Константе.

Как известно, в Ruby константы начинаются с заглавной буквы, отсюда и имена классов.

MyKlass = myklass

MyKlass          # => 'MyKlass'
MyKlass.name     # => 'MyKlass'
myklass.name     # => 'MyKlass'


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

Вообще, имя класса чаще носит просто информативный характер. Ведь используете класс вы не по имени, а с помощью той же переменной или Константы, в которой он хранится.

Курица или яйцо?


Тип Class, также как и остальные классы наследуется, от типа Object. Но, после такого:

Object.class       # => Class
Class.class        # => Class
Class.superclass   # => Module
Module.class       # => Class
Module.superclass  # => Object


разобраться, что первичнее — Object или Class невозможно. Как Class может быть константой, хранящей объект класса, экземпляром которого она и является? На самом деле Object, Class и Module — это первичные структуры, заложенные в интерпретаторе, и они не образуются друг из друга ruby-кодом, хотя Ruby успешно делает вид, что это так.

Интересный факт.

На самом деле в Ruby не существует методов класса (это которые мы, как нам кажется, описываем через def self.aaa). Есть только методы объектов, в том числе объектов типа Class.

Но об этом в следующий четверг…

Ссылки по теме


rhg.rubyforge.org/chapter02.html
rbdev.ru/2010/07/izuchaem-yadro-ruby-klassy-i-obekty/
stackoverflow.com/questions/1219691/why-object-class-class-in-ruby

Источник: http://habrahabr.ru/

 

3 комментария: