Рубиновое сумасшествие: класс против объекта? - PullRequest
65 голосов
/ 11 февраля 2011

Я только начал играть с JRuby.Это мой первый пост в рубине.Мне было трудно понять классы и объекты в Ruby.Это не означает, что классы и объекты в других объектно-ориентированных языках.для примера

Class.is_a? Object

возвращает true и

Object.is_a? Object

тоже .

, поэтому класс и объект обаобъекты

вот еще один

Class.is_a? Class

возвращает true и

Object.is_a? Class

тоже .

подождите, я еще не закончил

 Object.instance_of? Class
 Class.instance_of? Class

Оба истинны

 Object.instance_of? Object
 Class.instance_of? Object

Оба ложны.Да, ничто не может быть экземпляром объекта.

И

 Class.kind_of? Class
 Object.kind_of? Class

оба истинны

 Class.kind_of? Object
 Object.kind_of? Object

оба истинны

Так что оба точното же самое, тогда почему у нас оба эти ??

После еще нескольких копаний я написал этот простой метод для возврата списка методов, поддерживаемых обоими

irb(main):054:0> def print_methods(obj)
irb(main):055:1>    obj.methods.each do |mm|
irb(main):056:2*        puts mm
irb(main):057:2>    end
irb(main):058:1> end

Только различие между методами print_methods (Object) и print_methods (Class) равно

     Nesting

, если вложение означает наследование, похож ли объект на запечатанный класс ??

Может кто-нибудь объяснить мне, что все это значит?* Обновление: К комментарию Edds

Интересно, что я вижу много различий в списке методов в

c=Class.new
print_methods(c)

&

o=Object.new
print_methods(o)

Теперь японять Экземпляр класса действительно является экземпляром класса (а этот экземпляр класса на самом деле является объектом), а не экземпляром объекта.И даже этот экземпляр позволяет мне охватить другие экземпляры

  xx = c.new //works - c is an Object / and xx is a instance of an Object c
  yy = o.new //nope  - o is already a instance of an Object, so it cannot be instantiated again

Итак, наконец, Object действительно является экземпляром класса.Потому что

  xx.is_a? Class 

ложно, но

  xx.is_a? Object 

возвращает истину

Прав ли я, ??

Ответы [ 7 ]

38 голосов
/ 11 февраля 2011

По сути, главное, что нужно понять, это то, что каждый класс является экземпляром класса Class, а каждый класс является подклассом Object (в 1.8 - в 1.9 каждый класс является подклассом BasicObject). Таким образом, каждый класс является объектом в том смысле, что он является экземпляром подкласса Object, т.е. Class.

Конечно, это означает, что Class является экземпляром самого себя. Если это причиняет боль вашему мозгу, просто не думайте об этом слишком глубоко.

Object и Class являются is_a? Object

x.is_a? y возвращает true, если x.class == y or x.class < y, т. Е. Если класс x равен y, или класс x наследуется от y. Поскольку каждый класс наследует от объекта, x.is_a? Object возвращает true независимо от того, что x. (В любом случае в 1.8 в 1.9 есть также BasicObject, который сейчас является самым базовым классом в иерархии наследования).

Они также is_a? Class

И Object, и Class действительно являются классами, так что это не должно удивлять.

Они также instance_of? Class, но не instance_of? Object.

В отличие от is_a?, x.instance_of? y возвращает true только если x.class == y, а не если x.class является подклассом y. Так как x и y являются instance_of? Class, они не instance_of? Object.

верно, ничто не может быть экземпляром объекта.

Это не правда. Object.new.instance_of? Object верно.

kind_of

kind_of? - псевдоним для is_a?, см. Выше.

Так что оба абсолютно одинаковы, тогда зачем нам оба эти ??

Следует отметить, что до сих пор все верно для всех классов. Например. String.is_a? Object, String.is_a? Class и String.instance_of? Class имеют значение true, а String.instance_of? Object - false по тем же причинам, что и выше. (Также String.is_a? String и String.instance_of? String оба имеют значение false по одним и тем же причинам - String - это класс, а не строка).

Из этого нельзя сделать вывод, что все классы одинаковы. Это просто экземпляры одного класса.

Сравнение методов

Поскольку Object и Class являются классами, они оба имеют все методы экземпляра, определенные Class. Class дополнительно имеет метод синглтона nesting. nesting сообщает вам, в каком модуле вы сейчас находитесь, он не имеет ничего общего с наследованием.

Для любого данного класса TheClass.methods вернет методы экземпляра, определенные Class (например, superclass, который возвращает класс, от которого наследуется TheClass, и new, который создает новый экземпляр TheClass ) плюс одноэлементные методы, определенные этим классом.

В любом случае methods только сообщает вам, какие методы могут быть вызваны непосредственно для данного объекта. Он не говорит вам, какие методы могут быть вызваны для экземпляра класса. Для этого вы можете использовать instance_methods, который возвращает существенно отличающиеся результаты для Object и Class.

18 голосов
/ 11 февраля 2011

В Ruby все Object, включая классы и модули. Object - самый низкоуровневый класс (ну, в Ruby 1.9.2 также есть BasicObject, но это другая история).

См. Следующий вывод.

> Object.ancestors
# => [Object, Kernel, BasicObject] 
> Class.ancestors
# => [Class, Module, Object, Kernel, BasicObject] 
> Module.ancestors
# => [Module, Object, Kernel, BasicObject] 
> String.ancestors
# => [String, Comparable, Object, Kernel, BasicObject]

Как видите, и Class, и Module наследуются от Object.

Возвращаясь к своим первоначальным утверждениям, вы должны понимать разницу между

  • is_a?
  • kind_of'
  • instance_of?

Они не взаимозаменяемы. is_a? и kind_of? возвращают true, если другой является тем же классом или предком. И наоборот, instance_of? возвращает true только в том случае, если другой - того же класса.

> Class.is_a? Object
# => true 
> Class.kind_of? Object
# => true 
> Class.instance_of? Object
# => false 
2 голосов
/ 11 февраля 2011

Иерархия классов / метаклассов всегда немного озадачивает :) Для сравнения, вот та, что в Smalltalk ;в Ruby установка основана на тех же принципах, за исключением того, что она не имеет различий Behavior и ClassDescription, и есть модули и собственные классы, которые необходимо учитывать.

Полное объяснение объектной модели Smalltalk доступно в Pharo на примере , как указано в этом связанном вопросе .

2 голосов
/ 11 февраля 2011

Рамеш, в ruby ​​ все является объектом, и класс не является исключением.

попробуйте это в irb

ruby-1.9.2-p136 :001 > o = Object.new
=> #<Object:0x000001020114b0> 
ruby-1.9.2-p136 :002 > o.is_a? Class
=> false 
ruby-1.9.2-p136 :003 > o.is_a? Object
=> true 

в этом случае я создал экземпляр объекта и проверил, является ли он классом (false) или объектом (true).

Класс в ruby ​​- это некий объект шаблона, используемый для создания экземпляров этого класса. Извините, что это не супер ясно. Ключевой концепцией является то, что ruby ​​является чистым объектно-ориентированным языком, в отличие от Java.

1 голос
/ 06 мая 2018

В одном из ответов упоминается следующее:

По сути, ключевым моментом для понимания является то, что каждый класс является экземпляром класса Class, а каждый класс является подклассом Object.Таким образом, каждый класс является объектом в том смысле, что он является экземпляром подкласса Object, то есть Class.

Я просто хочу сказать это по-разному для тех, у кого есть небольшой поворот мозга.Сначала спросите себя: что такое пример в программировании?А что такое подкласс в программировании?Экземпляр - это просто реализованная вариация проекта (Класса).Подкласс - это просто класс (план), который наследуется от другого класса (план).Поэтому, когда вы создаете новый класс:

class Apple
end

Apple является экземпляром класса, то есть представляет собой реализованный вариант плана.Он берет план и заполняет детали (методы и переменные) своим собственным вариантом.Хорошо, проект наследует от другого проекта, который является Объектом.Таким образом, каждый класс является экземпляром Class, который является подклассом Object.

class A 
end
A.parent  
=> Object     
A.class  
=> Class

Примечание. Класс имеет модуль в своей цепочке наследования (возможно, модуль включен в класс в качестве смеси, поскольку родительским классом является объект?)

A.is_a?(Module)
 => true  

Экземпляры (A.new) класса A будут иметь свои собственные реализованные варианты A. Но они являются объектными экземплярами.Таким образом, мы должны различать экземпляры класса (например, конец класса A) и экземпляры объекта (a = A.new).Экземпляры объектов имеют другую цепочку наследования.Они представляют собой реализованный вариант плана экземпляра класса, а не вариант класса Class.

Это означает, что в их цепочке наследования не указан класс или модуль.Но скорее другие экземпляры объекта, поэтому, если A имеет экземпляры объекта, а B имеет экземпляры объекта и A наследует от B, когда мы создаем экземпляр нового объекта A, этот экземпляр будет иметь экземпляры B в своей цепочке наследования.

Они также будут наследоваться от Object, поскольку все в Ruby наследуется от Object.

a = A.new
 => #<A:0x007f966449b8d8> 
a.is_a?(Class)
 => false 
a.is_a?(Module)
 => false 
a.is_a?(Object)
 => true 

И это лучший способ подумать обо всем этом.Не углубляйся в свои мысли.Примите это так, как я написал.

1 голос
/ 23 декабря 2013

Как _why пишет в этой статье

объекты не хранят методы, могут только классы.

В первых двух разделах есть несколько хороших замечаний о классах и объектах

0 голосов
/ 08 июня 2012

Думайте о классах как о глобальных объектах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...