Определение типа объекта в рубине

365

Я буду использовать Python в качестве примера того, что я ищу (вы можете думать о нем как о псевдокоде, если вы не знаете Python):

>>> a = 1
>>> type(a)
<type 'int'>

Я знаю, в рубине я могу сделать:

1.9.3p194 :002 > 1.class
 => Fixnum 

Но так ли это правильно для определения типа объекта?

Зиппи Зепполи
источник
5
@ JörgWMittag Тем не менее AFAICR это то, что `type` делает в Python, хотя моя память нечеткая. Вам нужно isinstance или проверить ответы. Но просто сказать "НЕТ !!!" не очень полезно, правда? Вместо этого подумайте о том, чтобы быть образовательным.
Дэйв Ньютон,
4
@ JörgWMittag Хотя я сочувствую, OP предоставил код для имитации в Ruby. Если вы на самом деле не обучаете ОП, говоря «нет», IMO. И даже если вы это сделаете, скорее всего, это будет только для информации, так как OP определил, что он / она хочет через код.
Дейв Ньютон,
5
@ JörgWMittag - в Ruby все является объектом, поэтому нет примитивных типов, как в Python (int, long, boolean и т. Д.). В результате в Ruby классы являются определениями типов. Это также не ограничивается Ruby, слово класс и тип являются синонимами в нескольких других языках, и в более широком смысле в теории ООП.
ocodo
6
Поскольку мы действительно говорим о Ruby здесь, типы и классы являются синонимами, об этом не спорят, все значения являются объектами. Так что для тех, кто просто говорит о Ruby, классы - это типы. - ref: ruby-lang.org/en/about
ocodo
2
@ JörgWMittag Это эссе достаточно информативно, и я прочитаю остальное, когда у меня будет шанс. В частности, Кук, кажется, довольно четко формулирует (и обладает гораздо большим количеством базовых знаний, чем я), почему неверно утверждать (как это делал один из моих профессоров), что Python, Ruby и другие языки с динамической типизацией "на самом деле не являются объектами -ориентированный "(что он, вероятно, имел в виду, не осознавая этого, было то, что они не были ADT-ориентированными). Но в Ruby нет статической типизации, поэтому он не имеет ADT в том смысле, как описывает Кук, поэтому ваши возражения на основании этого различия не будут полезны.
Кайл Стрэнд

Ответы:

608

Правильный способ определения «типа» объекта, который является шатким термином в мире Ruby, - это вызов object.class.

Так как классы могут наследоваться от других классов, если вы хотите определить, принадлежит ли объект «к определенному типу», вы можете позвонить, object.is_a?(ClassName)чтобы узнать, имеет ли objectон тип ClassNameили является его производным.

Обычно проверка типов не выполняется в Ruby, но вместо этого объекты оцениваются на основании их способности реагировать на конкретные методы, обычно называемые « типизацией утки ». Другими словами, если он отвечает на методы, которые вы хотите, нет никаких оснований для конкретного типа.

Например, object.is_a?(String)он слишком жесткий, поскольку другой класс может реализовывать методы, которые преобразуют его в строку или заставляют вести себя идентично поведению String. object.respond_to?(:to_s)было бы лучшим способом проверить, что рассматриваемый объект делает то, что вы хотите.

Тадман
источник
13
-1. #classничего не возвращает тип объекта, он возвращает его класс . Имя должно быть мертвой раздачей. Класс и Тип - это две совершенно разные концепции в ОО.
Йорг Миттаг
78
@ Йорг W Mittag: я не согласен. «Класс» и «скорость процессора» (для примера) - это две совершенно разные концепции, но «класс» и «тип» - тесно связанные понятия. Например, вот что говорится в статье Википедии о классе : «В объектно-ориентированном программировании класс - это конструкция, которая используется для определения отдельного типа». Тэдман был полезным для спрашивающего.
Теему Лейсти
18
@ JörgWMittag В Ruby ближе всего к typeofC, JavaScript и другим class. В Ruby нет официальной системы протоколов, как в других языках, Objective-C является ближайшим родственником Smalltalk с этим. Если вы определяете «тип» как «объект, который отвечает на определенный набор методов с приемлемыми результатами», то на самом деле нет никакого способа утверждать это. Это просто слишком свободно. В большинстве случаев в Ruby при ссылке на тип объекта понимается, что вы говорите о классе. Я использовал термин «тип» в кавычках именно по этой причине.
tadman
14
@ Jörg W Mittag: Я продолжаю утверждать, что «класс» и «тип», безусловно, не совсем разные понятия в ОО, как показано в цитате. (Также: как вы объявляете переменную в Java Давая? Либо на тип или класс переменной, а затем по его имени: « int i» или « Integer j».) Тадман ответил на вопрос таким образом , что , казалось, удовлетворить и вопрошающего и общая аудитория, разъясняя терминологию, которую использует Ruby. Я не заинтересован в том, чтобы разбираться в академических прическах по тонкостям объектно-ориентированной терминологии, поэтому, пожалуйста, скажи последнее слово.
Теему Лейсти
11
@TeemuLeisti Большинство проблем здесь связано с тем, что все в Ruby является объектом, и поэтому имеет класс, тогда как практически во всех других языках есть примитивные типы, которые не являются объектами и не имеют классов, в отличие от объектов, которые делают. Когда нет такого понятия, как чистый тип, и нет способа формально определить его, значение становится особенно туманным в мире Ruby. Мац не строго придерживается какой-либо конкретной школы мысли здесь, кроме своей собственной.
tadman
81

Вы также можете попробовать: instance_of?

p 1.instance_of? Fixnum    #=> True
p "1".instance_of? String  #=> True
p [1,2].instance_of? Array #=> True
Аруп Ракшит
источник
44

Часто в Ruby вас не волнует, какой класс у объекта, по сути, вы просто заботитесь о том, чтобы он реагировал на определенный метод. Это известно как Duck Typing, и вы увидите это во всех видах кодовых баз Ruby.

Так что во многих (если не в большинстве) случаях лучше всего использовать Duck Typing, используя #respond_to?(method):

object.respond_to?(:to_i)
Стюарт М
источник
1
действительная точка. не отвечает на вопрос, но поражает дух вопроса.
user566245 23.09.15
@ user566245 что ж, он отвечает_? (: the_question), но, как вы сказали, он не отвечает на вопрос, а просто дает соответствующую информацию. Довольно уверен, что ответы должны ответить на вопрос.
Р. Ринкон
17

Я бы сказал "Да". Как сказал «Матц» нечто подобное в одном из своих выступлений, «у объектов Ruby нет типов». Не все это, а та часть, которую он пытается донести до нас. Почему тогда кто-то сказал: «Все есть объект»? Чтобы добавить, он сказал: «Данные имеют типы, а не объекты».

Таким образом, мы могли бы наслаждаться этим.

https://www.youtube.com/watch?v=1l3U1X3z0CE

Но Руби не волнует тип объекта, а только класс. Мы используем классы, а не типы. Все данные затем имеют класс.

12345.class

'my string'.class

Они также могут иметь предков

Object.ancestors

У них также есть мета-классы, но я сохраню вам детали об этом.

Как только вы узнаете класс, вы сможете посмотреть, какие методы вы можете использовать для него. Вот где нужен «тип данных». Если вы действительно хотите вникнуть в подробности, посмотрите вверх ...

"Рубиновая объектная модель"

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

Да! Класс является типом данных. У объектов есть классы, а у данных есть типы. Так что если вы знаете о базах данных, то знаете, что существует только конечный набор типов.

номера текстовых блоков

Дуглас Г. Аллен
источник
Например,Object.ancestors # => [Object, Kernel, BasicObject]
Дориан