Ruby: kind_of? vs. instance_of? vs. is_a?

В чем разница? Когда я должен использовать это? Почему их так много?

Ответ 1

kind_of? и is_a? являются синонимами. instance_of? отличается от двух других тем, что возвращает только true, если объект является экземпляром этого точного класса, а не подкласса.

Пример: "hello".is_a? Object и "hello".kind_of? Object return true, потому что "hello" является String и String является подклассом Object. Однако "hello".instance_of? Object возвращает false.

Ответ 2

В чем разница?

Из документации:

- (Boolean) instance_of?(class)
Возвращает true, если obj является экземпляром данного класса.

и

- (Boolean) is_a?(class)
- (Boolean) kind_of?(class)
Возвращает true, если class является классом obj, или если class является одним из суперклассов obj или модулей, включенных в obj.

Если это неясно, было бы хорошо знать, что именно неясно, чтобы документация могла быть улучшена.

Когда мне следует использовать какой?

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

Почему их так много?

Я бы не назвал два "много". Их два, потому что они выполняют две разные вещи.

Ответ 3

Это больше похоже на Ruby, чтобы спросить объекты, отвечают ли они на нужный вам метод, используя respond_to?. Это позволяет как минимальному интерфейсу, так и реализации выполнять нестандартное программирование.

Конечно, это не всегда применимо, поэтому есть возможность задать более консервативное понимание "типа", которое является классом или базовым классом, используя методы, о которых вы просите.

Ответ 4

Я также не стал бы называть два числа (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