Bug #6020
closedUnexpected is_a/kind_of behaviour
Description
=begin
I've noticed some inconsistent is_a?/kind_of? methods behavior in a very special cases
self.class #=> Object
BasicObject.is_a?(BasicObject) #=> true
Module.is_a?(Module) #=> true
Class.is_a?(Class) #=> true
Object.is_a?(Object) #=> true
BasicObject.is_a?(Module) #=> true
Integer.is_a?(Integer) #=> false
class A; end
A.is_a?(A) #=> false
module B; end
B.is_a?(B) #=> false
class C < Object; end
C.is_a?(C) #=> false
C.is_a?(Object) #=> true
C.is_a?(BasicObject) #=> true
C.is_a?(Module) #=> true
C.is_a?(Class) #=> true
c = C.new
c.is_a?(Module) #=> false
c.is_a?(Class) #=> false
It looks like it's because Class, Module, Object and BasicObject have class Class, superclass is set properly.
Anyway all is logical but not expected.
=end
Updated by shyouhei (Shyouhei Urabe) over 12 years ago
- Status changed from Open to Feedback
Can you show us your "expected behavior"?
Updated by MasterLambaster (Alex N) over 12 years ago
=begin
well, at least (({Integer.is_a?(Integer) #=> true})). I can live with that fact that the (({BasicObject.is_a?(Module) #=> true})) bearing in mind that the BasicObject is a Class
=end
Updated by peter_v (Peter Vandenabeele) over 12 years ago
On Tue, Feb 14, 2012 at 11:41 AM, Alex N masterlambaster@gmail.com wrote:
Issue #6020 has been updated by Alex N.
=begin
well, at least (({Integer.is_a?(Integer) #=> true})).
TL;DR : use is_a?
on an object of the class, not on the class itself.
Long version:
The confusion is that is_a? checks if the object is of class Integer,
not the Integer class.
So.
$ irb
1.9.3p0 :001 > i = 12
=> 12
1.9.3p0 :002 > i.class
=> Fixnum
i is an object of the Fixnum class.
1.9.3p0 :003 > i.is_a?(Integer)
=> true
yes, the object i is an Integer ...
1.9.3p0 :004 > i.is_a?(Fixnum)
=> true
... and also a Fixnum
1.9.3p0 :005 > Integer.class
=> Class
1.9.3p0 :006 > Integer.is_a?(Integer)
=> false
but the class Integer is not an Integer
(because Class does not inherit from Integer).
1.9.3p0 :007 > Class.ancestors
=> [Class, Module, Object, Wirble::Shortcuts, PP::ObjectMixin, Kernel,
BasicObject]
Class only inherits from Module, Object and BasicObject and mixes in some
additional functionality.
HTH,
Peter
--
*** Available for a new project ***
Peter Vandenabeele
http://twitter.com/peter_v
http://rails.vandenabeele.com
http://coderwall.com/peter_v
Updated by MasterLambaster (Alex N) over 12 years ago
=begin
Yes, i know how instance is_a? works. The problem is that the module owns the same functionality as well.
For example:
module A; end
A.class #=> Module
A.is_a?(A) #=> false
A.is_a?(A.class) #=> true
From implementation perspective it's totally ok: Module is not A.
But (({A.ancestors})) is (({[A]})), meanwhile (({Module.ancestors})) it the whole set of the core objects. At the same time module A is an BasicObject.
I'm not saying that it's completely wrong, but it feels confusing. On the other had it's really really edge case.
=end
Updated by rkh (Konstantin Haase) over 12 years ago
Yes, i know how instance is_a? works.
Apparently not.
def is_a?(module)
self.class.ancestors.include? module
end
A.is_a? A # false since Module.ancestors == [Module, Object, Kernel, BasicObject]
Module.is_a? Module # true since Module.class == Class and Class.ancestors == [Class, Module, Object, Kernel, BasicObject]
BasicObject.is_a? BasicObject # true since BasicObject.class == Class and Class.ancestors == [Class, Module, Object, Kernel, BasicObject]
Konstantin
On Feb 14, 2012, at 12:23 , Alex N wrote:
Issue #6020 has been updated by Alex N.
=begin
Yes, i know how instance is_a? works. The problem is that the module owns the same functionality as well.
For example:
module A; end
A.class #=> Module
A.is_a?(A) #=> false
A.is_a?(A.class) #=> trueFrom implementation perspective it's totally ok: Module is not A.
But (({A.ancestors})) is (({[A]})), meanwhile (({Module.ancestors})) it the whole set of the core objects. At the same time module A is an BasicObject.
I'm not saying that it's completely wrong, but it feels confusing. On the other had it's really really edge case.
=end
Bug #6020: Unexpected is_a/kind_of behaviour
https://bugs.ruby-lang.org/issues/6020Author: Alex N
Status: Feedback
Priority: Low
Assignee:
Category: core
Target version:
ruby -v: ruby 2.0.0dev (2012-02-14 trunk 34598) [x86_64-darwin11.3.0]=begin
I've noticed some inconsistent is_a?/kind_of? methods behavior in a very special cases
self.class #=> ObjectBasicObject.is_a?(BasicObject) #=> true
Module.is_a?(Module) #=> true
Class.is_a?(Class) #=> true
Object.is_a?(Object) #=> trueBasicObject.is_a?(Module) #=> true
Integer.is_a?(Integer) #=> false
class A; end
A.is_a?(A) #=> falsemodule B; end
B.is_a?(B) #=> falseclass C < Object; end
C.is_a?(C) #=> false
C.is_a?(Object) #=> true
C.is_a?(BasicObject) #=> true
C.is_a?(Module) #=> true
C.is_a?(Class) #=> truec = C.new
c.is_a?(Module) #=> false
c.is_a?(Class) #=> falseIt looks like it's because Class, Module, Object and BasicObject have class Class, superclass is set properly.
Anyway all is logical but not expected.
=end
Updated by marcandre (Marc-Andre Lafortune) over 12 years ago
- Status changed from Feedback to Rejected
Rejected as is_a?
conforms to its description and what many expect.
Alex: Maybe the behavior you are looking for is given by Module#<=
:
Integer <= Integer # => true
BasicObject <= Module # => false
# etc..