Визначення типу предмета в рубіні


364

Я буду використовувати 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 Хоча я співчуваю, ОП надав код для імітації в Ruby. Якщо ви насправді не навчите ОП, кажучи, що «ні» не корисно, IMO. І навіть якщо ви це зробили, це, ймовірно, буде лише інформаційним, оскільки ОП визначив, що він / він хотів через код.
Дейв Ньютон

5
@ JörgWMittag - у Ruby все є об'єктом, тому немає примітивних типів, як у Python (int, long, boolean тощо). В результаті в Ruby класи - це визначення типів. Це не обмежується і Ruby, і клас класу, і тип слова є синонімами для декількох інших мов, і в більш широкому плані - в теорії OOP
окудо

6
Оскільки ми тут справді говоримо про Ruby, типи та класи є синонімами, про це немає ніяких дискусій, усі значення є "Об'єкти". Тож для тих, хто просто говорить про Рубі, класи - це типи. - ref: ruby-lang.org/uk/about
ocodo

2
@ JörgWMittag Цей твір поки що досить інформативний, а решту я прочитаю, коли отримаю можливість. Зокрема, Кук, здається, чітко формулює (і маючи набагато більше знань, ніж у мене), чому неправильно стверджувати (як це робив один з моїх професорів), що Python, Ruby та інші динамічно набрані мови "насправді не є об'єктом "зорієнтована" (те, що він, мабуть, мав на увазі, не усвідомлюючи цього, - це те, що вони не орієнтовані на ADT). Але Рубі не є статично типізованим, тому у нього немає АДТ у тому сенсі, який описує Кук, тому ваші заперечення на основі цього розрізнення не є корисними.
Кайл Странд

Відповіді:


607

Правильним способом визначення "типу" об'єкта, який є хитним терміном у світі Рубі, є виклик object.class.

Оскільки класи можуть успадковувати інші класи, якщо ви хочете визначити, чи є об'єкт "певного типу", ви можете зателефонувати, object.is_a?(ClassName)щоб побачити, чи objectвін типу, ClassNameчи похідний від нього.

Зазвичай перевірка типу не робиться в Ruby, а натомість об'єкти оцінюються, виходячи з їх здатності реагувати на конкретні методи, які зазвичай називаються «типом качки ». Іншими словами, якщо він відповідає потрібним методам, немає жодної причини бути конкретним щодо типу.

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


13
-1. #classнічого НЕ повертає тип об'єкта, він повертає його клас . Назва має бути мертвою подачею. Клас і Тип - це два абсолютно різних поняття в ОО.
Йорг W Міттаг

78
@ Йорг W Міттаг: Я не згоден. "Клас" і "швидкість процесора" (щоб вибрати приклад) - це два абсолютно різні поняття, але "клас" і "тип" - тісно пов'язані між собою поняття. Наприклад, ось що говорить стаття Вікіпедії про клас : "У об'єктно-орієнтованому програмуванні клас - це конструкція, яка використовується для визначення різного типу". Тадман був корисним питаючому.
Teemu Leisti

18
@ JörgWMittag У Ruby найближче до typeofC, JavaScript та інших class. У Рубі не існує офіційної протокольної системи, як це є в інших мовах, при цьому об'єктив-C є найближчим родичем Smalltalk. Якщо ви визначаєте "тип" як "об'єкт, який відповідає певному набору методів з прийнятними результатами", то насправді цього немає можливості стверджувати. Це просто занадто вільно. Більшу частину часу в Ruby, маючи на увазі тип об’єкта, розуміється, що ви говорите про клас. Я саме використовував термін типу в лапках саме з цієї причини.
тадман

14
@ Йорг W Міттаг: Я продовжую стверджувати, що "клас" і "тип", безумовно, не є абсолютно різними поняттями в ОО, як це демонструє цитата. (Також: як ви оголошуєте змінну в Java Даючи? Або на тип або клас змінної, а потім по його імені: « int i» або « Integer j».) Тадман відповів на питання таким чином , що , здавалося, задовольнити і питається і загальну аудиторію, уточнюючи термінологію, яку використовує Ruby. У мене немає інтересу потрапляти в академічне роздвоєння волосся на більш точні моменти об'єктно-орієнтованої термінології, тому будь ласка, майте останнє слово.
Teemu Leisti

11
@TeemuLeisti Більшість проблем тут пов’язана з тим, що все в Ruby є об'єктом, і тому він має клас, тоді як практично в будь-якій іншій мові є примітивні типи, які не є об'єктами і не мають класу, на відміну від об'єктів, які роблять. Коли немає такого поняття, як чистий тип, і ніякого способу його формально визначити, значення в світі Рубі стає особливо туманним. Мац не суворо дотримується жодної конкретної школи думки, окрім своєї власної.
тадман


44

Часто в Ruby, ви насправді не хвилюєтеся, який клас об'єкта, як наслідок, вам просто цікаво, щоб він реагував на певний метод. Це відомо як Duck Typing, і ви побачите його у всіляких кодових базах Ruby.

Тож у багатьох (якщо не в більшості) випадках найкраще використовувати набір качок, використовуючи #respond_to?(method):

object.respond_to?(:to_i)

1
дійсна точка. не відповідає на питання, але вражає дух питання.
користувач566245

@ user566245 добре він відповідає_то? (: the_question), але, як ви вже сказали, він не відповідає на питання, просто дає відповідну інформацію. Для відповіді на запитання потрібно досить впевнені відповіді.
Р. Рінкон

17

Я б сказав "Так". Як "Мац" сказав щось подібне в одному зі своїх розмов, "у предметів Рубі немає типів". Не все, але частина, яку він намагається перейти до нас. Чому б хтось тоді сказав "Все є об'єктом"? Додамо, він сказав: "Дані мають типи, а не об'єкти".

Тож ми можемо насолодитися цим.

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

Але Рубі не дуже цікаво тип об’єкта, а саме клас. Ми використовуємо класи, а не типи. Тоді всі дані мають клас.

12345.class

'my string'.class

Вони також можуть мати предків

Object.ancestors

У них також є мета-класи, але я збережу вам деталі на цьому.

Як тільки ви дізнаєтесь про клас, тоді ви зможете шукати, які методи ви можете використовувати для цього. Ось де потрібен "тип даних". Якщо ви дійсно хочете розібратися в деталях, подивіться ...

"Модель об'єкта Ruby"

Це термін, який використовується для того, як Рубі обробляє об'єкти. Це все внутрішнє, тому ви насправді не бачите багато цього, але приємно це знати. Але це вже інша тема.

Так! Клас - тип даних. Об'єкти мають класи, а дані мають типи. Отже, якщо ви знаєте про бази даних, то ви знаєте, що існує лише обмежений набір типів.

текстові блоки номерів


Наприклад,Object.ancestors # => [Object, Kernel, BasicObject]
Доріан
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.