Project

General

Profile

Actions

Bug #6020

closed

Unexpected is_a/kind_of behaviour

Added by MasterLambaster (Alex N) almost 13 years ago. Updated almost 13 years ago.

Status:
Rejected
Assignee:
-
Target version:
-
ruby -v:
ruby 2.0.0dev (2012-02-14 trunk 34598) [x86_64-darwin11.3.0]
Backport:
[ruby-core:42607]

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) almost 13 years ago

  • Status changed from Open to Feedback

Can you show us your "expected behavior"?

Updated by MasterLambaster (Alex N) almost 13 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) almost 13 years ago

On Tue, Feb 14, 2012 at 11:41 AM, Alex N 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) almost 13 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) almost 13 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) #=> 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


Bug #6020: Unexpected is_a/kind_of behaviour
https://bugs.ruby-lang.org/issues/6020

Author: 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 #=> 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

--
http://bugs.ruby-lang.org/

Updated by marcandre (Marc-Andre Lafortune) almost 13 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..
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0