Ruby: kind_of? vs. instance_of? проти is_a?


487

Яка різниця? Коли я повинен використовувати який? Чому їх так багато?


18
Щодо того , чому так is_a?і kind_of?є: я вважаю , що це частина філософії дизайну Рубі. Python би сказав, що існує лише один спосіб зробити щось; У Рубі часто є синонімічні методи, тому ви можете використовувати той, який звучить краще. Це питання переваги. Частково це може бути пов’язано з японським впливом: мені кажуть, що вони використовуватимуть інше слово для однієї і тієї ж кількості, залежно від речення, щоб зробити це красивішим. Матц, можливо, вніс цю ідею у свій мовний дизайн.
Натан Лонг

@NathanLong Я не думаю, що японські лічильники мають багато спільного з цим; всі мови мають якусь угоду, і ви не можете більше замінювати один лічильник на інший (наприклад, не можна використовувати лічильник циліндрів для плоских предметів; це просто неправильно). І це більше стосується семантики, ніж ейфонії.
Кейсі

Відповіді:


621

kind_of?і is_a?є синонімами.

instance_of?відрізняється від двох інших тим, що повертається лише в тому випадку, trueякщо об'єкт є екземпляром цього точного класу, а не підкласом.

Приклад:

  • "hello".is_a? Objectі "hello".kind_of? Objectповертаємось trueтому, що "hello"є Stringі Stringє підкласом Object.
  • Однак "hello".instance_of? Objectповертається false.

77
Це просто читається іноді краще. Подумайте @honda.kind_of? Carі @person.is_a? Administrator, Рубі, все про естетику. Насправді помічайте граматичну помилку ... при активній підтримці ви можете написати @person.is_an? Administrator:) ... Це, можливо, вже перетворилося на ядро ​​Ruby.
rfunduk

2
хе, це цікава причина. ти можеш зламати це, ти як ти можеш перекрити, kind_of?але ні is_a??
Клавдіу

3
@thenduks, is_an?не знаходиться в рубіні-1.9.2-p0. @Claudiu, ні. is_a?це лише псевдонімkind_of? . Обидва методи ВИКЛИК тієї ж функції з, rb_obj_is_kind_of.
ma11hew28

9
@Matt: Ви можете змінити псевдонім, не змінюючи функцію псевдоніму. Так що так, ви можете переосмислити, kind_of?не змінюючи їх is_a?.
sepp2k

4
Де цей is_an?метод ActiceSupport ?! Його немає в поточній версії рейок, і я не можу знайти нічого в Google про те, що це також застаріло.
Том Лорд

22

Яка різниця?

З документації:

- ( Булева )instance_of?(class)
Повертає, trueякщо objце екземпляр даного класу.

і:

- ( булева ) is_a?(class)
- ( булева )kind_of?(class)
Повертає, trueякщо classце клас obj, або якщо classце один із надкласів objабо модулів, що входять до складу obj.

Якщо це незрозуміло, було б непогано знати, що саме незрозуміло, щоб документацію можна було покращити.

Коли я повинен використовувати який?

Ніколи. Використовуйте замість цього поліморфізм.

Чому їх так багато?

Я б не назвав двох "багатьох". Їх є дві, бо вони роблять дві різні речі.


3
Я думаю, що моя плутанина полягала в тому, що їх є 3, а 2 просто роблять те саме і мають різні назви. Про використання поліморфізму - я згоден, але стандартна бібліотека для рубінів сповнена кожного з них
Клавдіу

4
Що ви маєте на увазі під поліморфізмом? Це те саме, що качка набирає текст?
Ендрю Грімм

2
Так, вони однакові. Типи качок - це форма поліморфізму.
SpaceGhost

3
Так, часто краще займатися поліморфізмом, так, але є випадки на кордоні, коли ви дійсно хочете знати, що у вас є певний клас, наприклад, коли ви маєте справу з файлами.
Automatico

6

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

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


5
Це залежить від ситуації. І коментар, і блог можуть відповісти на create_at. У такій ситуації є_a? Більше підходить ІМХО
Пеньковський

Це не має сенсу, якщо вам потрібно було відрізнити коментар та об’єкт блогу один від одного, ви просто не використовуєте create_at для цього. Це не виключає, що ви можете написати метод, який бере об’єкт, який відповідає на create_at. Якщо йому не потрібно нічого іншого, щоб виконувати свою роботу, тоді ви можете сміливо використовувати його в коментарях чи блогах або в будь-якій іншій моделі ActiveRecord.
Кінгдон

3

Я також не закликав би два ( is_a?і kind_of?псевдоніми одного і того ж методу), але якщо ви хочете побачити більше можливостей, зверніть свою увагу на #classметод:

A = Class.new
B = Class.new A

a, b = A.new, B.new
b.class < A # true - means that b.class is a subclass of A
a.class < B # false - means that a.class is not a subclass of A
# Another possibility: Use #ancestors
b.class.ancestors.include? A # true - means that b.class has A among its ancestors
a.class.ancestors.include? B # false - means that B is not an ancestor of a.class

1
Дякую - я справді запитував у загальному сенсі про те, "яку інформацію про тип часу можна зібрати в Ruby і як" - і це дає достатньо прикладів
Клавдіу,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.