Ruby:kind_of?与instance_of?与is_a?


487

有什么区别?我什么时候应该使用哪个?为什么会有这么多?


18
至于为什么都is_a?kind_of?存在:我想这是部分Ruby的设计理念。Python会说应该只有一种方法可以做某事。Ruby通常具有同义方法,因此您可以使用听起来更好的方法。这是一个偏好问题。这可能部分是由于日语的影响:有人告诉我,他们将根据句子对相同的数字使用不同的单词,以使其听起来更好。Matz可能已经将这个想法带入了他的语言设计中。
内森·朗

@NathanLong我认为日本柜台与它没有太大关系;所有语言都有某种协议,您不能在大多数时间里用一个计数器代替另一个计数器(例如,您不能将圆柱计数器用于平面对象;这是错误的)。而且它与语义有关,而不是谐音。
Casey

Answers:


621

kind_of?并且is_a?是同义词。

instance_of?与其他两个区别在于,仅true当对象是该确切类的实例而不是子类的实例时才返回。

例:

  • "hello".is_a? Object"hello".kind_of? Object返回,true因为"hello"StringString的子类Object
  • 但是"hello".instance_of? Object返回false

77
有时它读起来更好。想@honda.kind_of? Car@person.is_a? Administrator,红宝石是所有关于美学。实际上,请注意语法错误...在活动支持下,您可以编写@person.is_an? Administrator:)...实际上,到现在为止,它可能已进入Ruby核心。
rfunduk 2010年

2
嘿,这是一个有趣的原因。你能打破这个吗?像你可以覆盖kind_of?但不能is_a?吗?
Claudiu

3
@thenduks,is_an?不在ruby-1.9.2-p0中。@Claudiu,不。is_a?只是的别名kind_of?。两种方法都调用相同的c函数rb_obj_is_kind_of
ma11hew28 2011年

9
@Matt:您可以覆盖别名而不覆盖别名函数。因此,可以覆盖kind_of?而不覆盖is_a?
sepp2k 2011年

4
该ActiceSupport is_an?方法在哪里?它不是当前的Rails版本,在Google上我也找不到任何有关它已被弃用的信息。
汤姆·罗德

22

有什么区别?

从文档中:

-(布尔instance_of?(class)
返回trueif obj是给定类的实例。

和:

-(布尔值is_a?(class)
-(布尔值kind_of?(class)
返回trueif class是的类obj,或者class是包含的的超类之一obj或模块之一obj

如果不清楚,最好弄清楚到底是什么还不清楚,以便可以改进文档。

我什么时候应该使用哪个?

决不。请改用多态。

为什么会有这么多?

我不会叫两个 “很多”。它们有两个,因为它们做两种不同的事情。


3
我认为我的困惑是有3个,而2个只是做相同的事情而有不同的名称。关于使用多态性-我同意,但红宝石标准库已满每一项的用途
克劳迪乌

4
多态是什么意思?与鸭子打字一样吗?
安德鲁·格林

2
是的,他们是一样的。鸭子打字是多态的一种形式。
SpaceGhost

3
通常,进行多态性更好,是的,但是在某些边界情况下,您确实想知道自己具有特定的类,例如在处理文件时。
Automatico

6

使用,更像Ruby询问对象是否响应您需要的方法respond_to?。这允许最少的接口和不带意识的编程实现。

当然,它并不总是适用的,因此,仍然有可能使用您要询问的方法来询问对“类型”(类或基类)的更保守的理解。


5
这取决于情况。评论和博客都可以响应created_at。在这种情况下is_a?更合适的恕我直言
penkovsky

这没有任何意义,如果您需要将Comment和Blog对象彼此区分开,则根本不会使用created_at来做到这一点。这并不排除您可以编写一个方法,该方法采用一个对象来响应created_at。如果它不需要其他任何工作,则可以在Comment或Blog或其他任何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中收集什么运行时类型信息以及如何进行收集”-这提供了很多示例
Claudiu 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.