Ruby: kind_of?против instance_of?против is_a? - PullRequest
460 голосов
/ 08 октября 2010

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

Ответы [ 4 ]

584 голосов
/ 08 октября 2010

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.

20 голосов
/ 08 октября 2010

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

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

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

и

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

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

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

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

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

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

6 голосов
/ 09 мая 2013

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

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

3 голосов
/ 10 июня 2013

Я бы также не назвал два многие (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
...