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

    Кто изучает 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
    Поделиться публикацией
    Похожие публикации
    Ой, у вас баннер убежал!

    Ну. И что?
    Реклама
    Комментарии 64
      +4
      Ну, так а где удивляться то?) Сдаётся мне, что во всех языках/технологиях с более-менее развитым rtti всё аналогично. Например, в java/c# тоже «класс это объект». На самом деле тут путаются определения ООП-понятий класс/объект в чистом виде и конкретными названиями сущностей в языке программирования. «Объект» Class это просто носитель метаинформации каждого объекта. Ничего странного в том, что это тоже экземпляр («объект») какого-то класса (читай «типа») нету :)
        +3
        В Java, есть набор объектов называемых Class, но это лишь конвенция в API интроспекции. Это не те же сущности, которые порождают новые объекты.
        В потомках Smalltalk классы — полноправные объекты, которые можно в реальном времени менять.
          0
          В руби объект Object не носит метаинформацию о классах, а является полноценным объектом с кучей методов.
          >> Object.methods
          => [«private_class_method», «inspect», «name»… урезано… ]
            –4
            myklass.class.getMethods(), String.class.getFields() и т.д. в Java. В чём отличие непонятно.
              0
              Да не, и в Java Object — полноценный объект с какими-то методами, не очень вас понял :) Метаинформация носится отдельно, как раз с помощью объекта класса Class. Также он же и носит информацию для такого же полноценного рефлекшена итд.
            –6
            Вот в JavaScript-e класс — действительно объект, без всякой странной магии.
            А в «классических» ООП-языках — нет.
              +2
              Все книги по Руби начинаются словом — все сущности — объекты.
              Это нужно понять с самого начала.
              Так же как и то, что все папки и файлы в линуксе — это файлы.

              А за статью — спасибо. Как раз штудирую Руби — вчера добрался до хешей.
              Увлекательно, чёрт побери!

                0
                а если не секрет по чему штудируете? по какой литературе, просто интересно тоже, но встал на установке Руби и запуске первого проекта под виндой) черт это оказалось так трудно)
                  +1
                  Самый надёжный партнёр для Windows — rubyinstaller.org/. Eсли кто на маке то RVM!
                  По поводу книги, пройдите rubylearning.com/. Потом можно братся за более «advanced» книжку.
                  +2
                  А — Мне нечем заняться;
                  Б — Я хочу до конца выучить хоть один ЯП и начать на нем писать;
                  В — Я увидел листинг на руби и понял что там делается, даже не вникая в код;
                  Г — Я хочу поднять проект на рельсах;
                  Д — Я в восторге от подхода этого ЯП к поставленным задачам, листинга, возможностью написать одно и тоже разными способами;

                  Только что увидел что «по чему» отдельно )
                  А я отвечаю как «почему» )

                  Продолжим по лит-ре:
                  Начинать нужно из того что есть. Главное — определится какой уровень у Вас уже есть.
                  Если Вы уже писали на си или джаве — то вам прямой путь к вот этому:

                  Хэл Фултон Программирование на языке Ruby The Ruby Way — ISBN 5-94074-357-9.
                  У меня от нее мозги сплавились — отличная книга, но не мой уровень. Я чувствую неуютно себя с ней. Я к ней обязательно вернусь. Но позже.

                  Рубивики — ru.wikibooks.org/wiki/Ruby — очень помогает.

                  Крис Пайн «Учись программировать» — www.shokhirev.com/mikhail/ruby/ltp/title.html — вот первое что нужно прочесть, если лвл скила невысок.

                  Можно заюзать вот это еще — www.linuxshare.ru/docs/devel/languages/ruby/ruby.html — но как по мне — это больше материал к преподаванию в тех вузе.

                  Библия — Programming Ruby: The Pragmatic Programmers' Guide Thomas D., Hunt A., библия-то библией, но нихтферштейн, елки-палки. Там уже второе или третье издание доступно — а ее никак не переведут на русский.

                  Сейчас я учусь по — Фицджеральд М. Изучаем Ruby — isbn: 978-5-9775-0225-2.
                  Отличная вещь. Подойдет как и оболтусу, как я, так и профи.

                  Далее — habrahabr.ru/blogs/ruby — он тоже помогает.
                  Особенно цикл статей Покорим Ruby вместе! — habrahabr.ru/blogs/starting_programming/48559. Там не сколько сами статьи — сколько комментарии. Порой пара комментов лучше половины статьи.

                  Брюс А., Тейт Ruby on Rails. Быстрая веб-разработка ISBN: 5-9775-0224-9 — ее я юзаю как вводную в RoR.

                  И мой Вам совет — если решили кодить на руби — смените платформу.
                  На линуксе Вы будете чувствовать себя в разы комфортнее.
                  Хотя бы ради полноценной поддержки utf-8.

                    0
                    писал второпях) поэтому по чему вышло))
                    понял
                    я верстальщик, решил изучить вот один из языков программирования и хочу начать реально писать, вот )
                      0
                      не забывайте и про AWDR by Sam Ruby, Dave Thomas, David Heinemeier Hansson. тоже библия, но по рельсам :)
                    +1
                    Папки в линуксе? ПАПКИ?
                    0
                    Такое впечатление, что кусок выдран из книги и переведён промтом.reverse
                      +1
                      «Metaprogramming Ruby: Program Like the Ruby Pros» от Paolo Perrottа (@nusco). Был на презентации книги в Японии на RubyKaigi 2010.
                        0
                        Следуюший пост будет про «singleton» или «eigenclass».
                          0
                          Почти. Пошел искать книгу на скачку.
                          +1
                          Может имеет смысл добавить ссылку на книгу?

                          Ну и при всем уважении и благодарности за статью. критические комменты:

                          1) что-то не очень на «Metaprogramming Ruby» похоже, у Paolo Perrotta емнип все гораздо более прозрачно и понятно. Я, пожалуй, согласен с FanKill. Но тут я больше не Вас критикую, а скорее расхваливаю книгу (вдруг какого-нибудь хабраюзера отпугнет эта статья от книги). Если кто-то собрался читать «Metaprogramming Ruby», пусть смело читает: книжка отличная, написана ну очень-очень понятно.

                          2) Позвольте порекомендовать Вам использовать диаграмы как это делает Paolo.
                          Глядите, одна картинка вроде этой способно прояснить ситуацию имхо лучше чем вся Ваша статья. Если будете еще писать на забывайте плиз о картинках.
                        0
                        Ох-ох, простите, в первую-то линку не заглянул. В прочем, тема реализации в топики не раскрыта, потому не так страшно :)

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

                        P.S. Напомним, что Class < Module, хоть это и сокрыто в дебрях, но почти все, что сказано про классы, касается и модулей. Обычно даже наоборот пишут про модули, а потому говорят, что класс — тот же самый модуль, но умеющий инстанцировать объекты.
                        Class.new.methods — Module.new.methods #=> [«superclass», «allocate», «new»]
                          0
                          Хорошие слайдики, спасибо.
                            0
                            Почему-то не доступен сайт, а там неплохие статейки, надеюсь еще поднимется.
                              0
                              вернул на место %) Переезжаю на новый блог-engine, поэтому закрыл его временно.
                            +2
                            > разобраться что первичнее — Object или Class невозможно. Как Class может быт константой, хранящей объект класса, к классу которого она является?

                            вы взорвали мой мозг
                              +1
                              afaik, во всех everything-is-an-object языках в крайоне корней дерева классов начинается странная магия.
                                0
                                исправил )
                                –1
                                Нет, не понять мне японский подход к синтаксису…
                                  0
                                  Если это вы о моем синтаксисе, то пинок принят — на русском пишу хуже чем на компьютерном )
                                    0
                                    :)) Даже и не думал пинать! Хорошо пишете, технично :)

                                    Я про сам Ruby: синтаксис у него построен по какой-то своей хитрой логике, принять её непросто. Японец всё же разработал, и мыслит как-то… по-японски :)

                                    Видели японские шоу на YouTube? ну разве может такое прийти в голову нам, или европе, или американцам? :)) субъективный такой взгляд, фактами не подтвердить.
                                      +1
                                      Элементарная — самая логичная логика!
                                      Не привязанная к одному решению со старта.

                                      Не стоит судить про ЯП через мувики на ютубе ) А то, исходя из Вашей логики, ЯП, который будет написан русским, вообще не стоит учить остальному миру, т.к. «умом Россию не понять».
                                        0
                                        Язык 1С не стоит учить во всём мире :D
                                    0
                                    А что в синтаксисе не понятного? Впервые слышу такое, что Ruby ругают за синтаксис, много раз слышал о Perl'е, но Ларри Волл как бы тоже не японец :)
                                      0
                                      :))) Ругать не собираюсь: рискую зарваться в своей неграмотности с Ruby.
                                      Однако для человека привыкшего к стройной логичности C и Python — субъективно, руби выглядит очень заковыристо и необычно :) Примеры: ':key' ключ хэша, '|key, value|' в цикле по нему же. Очень странный взгляд на «как оно должно быть»

                                      А Перл — вообще ну его. Идея кратко излагать алгоритмы — конечно, хорошая, но… вот что получилось :))
                                        0
                                        :key — это просто базовый тип Symbol, представляющий из себя интернализированную строку (а не полноценный объект String)

                                        Для хэша в качестве ключа может использоваться совершенно любой объект.
                                        Т.е. допустимым является:
                                        hash = {}
                                        hash[:key] = «value»
                                        hash[2] = «value 2»
                                        hash[«22»] = :key
                                        hash[hash.class] = 2
                                        ну и т.д. :)

                                        Потому когда используется hash.each_pair{ |key,value|… } в качестве key может быть переменная совершенно любого вида.
                                          0
                                          Ну начнём с того, что это и не цикл вовсе…
                                            0
                                            то, что в Ruby называется итератором легче всего представить как цикл, который проходит по коллекции.
                                              0
                                              то что в Ruby называется итератором, им и является.
                                                0
                                                прочитайте еще раз мой комментарий, я не утверждал в нем, что итератор является циклом, хотя все это достаточно условное разделение, как по мне. Я лишь утверждал, что людям, не знакомым с итераторами или самим термином итераторы легче воспринимать как циклы в которых обходится коллекция.
                                                  0
                                                  твой комментарий больше похож на то, что в Ruby есть «подобие» итератора, который является циклом, проходящим по коллекции. Итераторы же не уникальная вещь, существующая только в Ruby, и потому логичнее было бы писать, что «итератор легче всего представить как цикл, который проходит по коллекции».
                                                    0
                                                    Уникальная? в Питоне тоже есть итераторы: например range(100). Аналогично?
                                                      0
                                                      в этом Aesthete может убедиться пройдя по собственной сылке=)

                                                      вообще эта тема — софистика и демагогия. в данном случае от того, как судно назовешь ничего не измениться в его способности плавать.
                                                        0
                                                        вы читаете оба через строку что ли? я и написал, что итераторы существуют много где и писать, что именно в Ruby итераторы похожи на циклы, в которых обходится коллекция — не очень верно. Потому что итераторы в любом языке должны себя так вести.
                                              +1
                                              :blabla — это объект класса Symbol. символы стоит воспринимать как строки(для простоты). Сиволы хороши тем, что «blabla» и «blabla» — два экземпляра класса Stirng, а для :blabla и :blabla создается лишь один объект. Именно благодаря этому символы используются очень часто в качестве ключей (т.к. экономят память).

                                              Начиная с Ruby 1.9 символы могут также проходить проверку регулярными выражениями и т.д… что способствует тому, чтобы думать о них как о строках. Еще с 1.9 для ключей-символов принят удобный синтаксис:

                                              вместо:
                                              hash={:symbol=>«тут какая-то строка», :color=>"#cc0000"}

                                              мы можем использовать:

                                              hash={symbol: «тут какая-то строка», color: "#cc0000"}
                                                0
                                                Кстати отличная идея отличать «константные», «внутренние» строки от тех что предназначены для пользователя. А выглядит всё равно странно :)
                                                  0
                                                  Не надо воспринимать символы как строки. Лучше хотя бы как числа.
                                                    0
                                                    ну мне он больше на строки смахивают… можно даже так сделать:

                                                    :'My name is Vladimir.'.class #=> Symbol
                                                      0
                                                      Это интернированые строки. Грубо говоря интерпретатор генерирует для каждого символа числовое значение, так что для одинаковых символов оно будет одно и тоже, а для разных отличается (там внутри глобальная хэш-таблица). :asdf == :asdf намного быстрее по производительности чем «asfd» == «asdf». И кстати для символов не действует сборщик мусора.
                                                        0
                                                        По поводу сборщика мусора не знал, а по поводу того, что символ имеет числовое представление мне было известно, не подскажите там разрядность?
                                                          0
                                                          * какая там разрядность
                                                            0
                                                            unsigned long минус 8 бит
                                                  +1
                                                  Ха, а я вот как раз про Python считаю, что если исходник (отступы) будет поврежден, то сложно его будет прочитать и заставить работать.

                                                  С ключем :key нет проблем, не нравится, используйте [«key»] — одно дело, что это будет очень неверно, а уж |key, value| ничем не хуже $array as $key=>$value в PHP читается.

                                                  В общем странно, но как раз после C (C++) читать Ruby вообще радостно.

                                                  Хотя и наверное сильно субъективно, но мне после Perl, PHP, JavaScript синтаксиса Ruby вообще интуитивно понятным кажется, даже если не знаешь как и что делать.
                                                    0
                                                    Хм, просто не нужно повреждать отступы :) кстати до знакомства с Питоном тоже казалось дикостью форматировать отступы. первые 100 строк кода (и то по книжке) — и уже ненавижу даже фигурные скобочки: ну они ведь совсем лишние, верно? :)))

                                                    С PHP вообще всё что ни сравни — лучше будет. Тугой как палка при разработке, и динамический BrainFuck для… тех кто поддерживает код :)))
                                                      0
                                                      Ну случается, что повреждаются, как-то смущает этот факт подобной блочности, как раз после СИ подобных языков :)

                                                      Ну PHP хаять не буду, перешел на него с Perl по нужде расширения и так сказать командной работы, задачи решает вполне своего уровня, иногда даже проще и быстрее, что-то написать и проверить на нём чем например на Ruby или Perl, какой-то он simple oriented.
                                              0
                                              dapi, спасибо за статью. Хотя она и написана в роде ревью и по предназначению не подходит ни для начинающих, ни для опытных.
                                              Хочется услышать больше о своих, личных, находках в ходе изучения данной темы в Рубы.
                                                0
                                                мне вообще не понравилось.

                                                Для новичков слишком мало информации и она представлена в каком-то сильно сжатом непонятном виде, а для программистов более высокого уровня все это давно пройденный этап. Вопрос: какой смысл статьи?

                                                Не хочу обидеть автора, статьи по Ruby на русском — дефицит и это похвально, что человек пытаетсяэтот дефицит побороть. Просто хочу пожелать автору писать более объемные статьи, а не «заметки». Удачи с написание новых статей, уверен вы примите критику ко вниманию и в следующий раз все мы увидим настоящий шедевр ;-)
                                                +1
                                                class NilClass
                                                  def nil? 
                                                    false 
                                                  end
                                                end
                                                class Object
                                                  def nil?
                                                    true 
                                                  end
                                                end
                                                  0
                                                  Цитатa из книги «Прагматика Онтологии»:

                                                  Замыкание системы объектных моделей: метаонтология
                                                  К проблематике конструирования онтологий в полной мере относится упомянутый тезис об онтологической относительности, когда наше знание об объектах, описываемых на языке одной теории, можно разбирать лишь на языке другой теории, который в свою очередь, должен рассматриваться в отношении к языку следующей теории, и т.д. до бесконечности. Например, в этом смысле МДСРП нуждается во внешнем определении ряда слагающих ее элементов: понятий «класс», «атрибут» и др. (рис. 1).
                                                  «Технологической реакцией» на онтологическую относительность является создание такого языка концептуальной спецификации «Предметной Области», который обеспечил бы обрыв бесконечной онтологической цепочки, т.е. обеспечил бы и самоописание, и спецификацию любой другой модели. Иными словами, для разработки приложений необходимо построить семантически замкнутую систему объектных моделей, которая включила бы в себя и МДСРП, и прикладные онтологии, и любые денотативные объектные модели. Такая задача решается путем построения «онтологии онтологий», или метаонтологии [Смирнов, 2000].
                                                  На рис. 2 представлен вариант такой метаонтологии, где включаемый в каждую онтологию фрагмент МДСРП дополнен двумя разновидностями объектов: АТРИБУТ и КЛАСС. Поскольку КЛАСС имеет тот же тип, что и ОБЪЕКТ, то ОБЪЕКТ, и все его подвиды семантически суть классы.

                                                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                  Самое читаемое