Looking for object.inherits?(Classname)

I’m looking for a way to make sure an object being passed is in some
class
family, or to say it otherwise, inherits some specific class, but not
necessarily directly. In fact, it could be a great-great-grandparent
class, and
that would be okay, and needs to be okay. Is there something where I
can take
an object and go

unless object.inherits?(MyClass)
raise SyntaxError, “etc.”
end

???

Sorry, but could not find this in my pickaxe book.

Hi –

On Wed, 20 Jan 2010, Xeno C. wrote:

???

Sorry, but could not find this in my pickaxe book.

object.is_a?(MyClass)

or

object.kind_of?(MyClass)

(same method, two different names).

David

On Wed, 20 Jan 2010, Xeno C. wrote:

Xeno C. wrote:

Looks like the method I use is “ancestors”.

Whoops, that means I misunderstood. Sorry.

David

On Jan 19, 2010, at 8:53 PM, David A. Black wrote:


David A. Black
Senior Developer, Cyrus Innovation Inc.
THE COMPLEAT RUBYIST, Ruby training with Black/Brown/McAnally!
January 22-23, Tampa, Florida
Info and registration at http://www.thecompleatrubyist.com

irb> string=“string”
=> “string”
irb> string.class
=> String
irb> string.class.ancestors
=> [String, Enumerable, Comparable, Object, Kernel]
irb> string.is_a?(String)
=> true
irb> string.is_a?(Comparable)
=> true
irb> string.kind_of?(Kernel)
=> true

It depends on whether you have an instance of the class or the class
object itself.

Xeno said that he had an object. I think David understood perfectly
and his answer is exactly what you want.

-Rob

Rob B. http://agileconsultingllc.com
[email protected]

Xeno C. wrote:

Looks like the method I use is “ancestors”.

2010/1/20 Xeno C. [email protected]:

I’m looking for a way to make sure an object being passed is in some class
family, or to say it otherwise, inherits some specific class, but not
necessarily directly. In fact, it could be a great-great-grandparent class,
and that would be okay, and needs to be okay. Is there something where I
can take an object and go

unless object.inherits?(MyClass)
raise SyntaxError, “etc.”
end

First of all that would not be a SyntaxError because the syntax is not
affected. Using this error type will create misleading error
messages.

Here are all the ways that I am aware of (trying to summarize what
others have posted so far):

irb(main):010:0> a = []
=> []
irb(main):011:0> a.class.ancestors
=> [Array, Enumerable, Object, Kernel, BasicObject]
irb(main):012:0> a.class.ancestors.include? Enumerable
=> true
irb(main):013:0> a.kind_of? Enumerable
=> true
irb(main):014:0> a.is_a? Enumerable
=> true
irb(main):015:0> Enumerable === a
=> true
irb(main):016:0>

Note that I do not recommend using the test from line 12 as it is
likely much more inefficient than the other ones. The test from line
15 is especially suited for use with “case” statements as in

case a
when Enumerable
puts “it’s enumerable”
when Array, Hash
puts “It’s a special enumerable”
when Integer
puts “You can count on me.”
else
puts “No idea about a.”
end

Another note: more often than not it is not necessary to test for the
type of an object. You rather invoke those methods on it that you
expect it to implement. You will get an exception anyway if the
object does not implement the method (NoMethodError). You can find
more details about this concept under the label “duck typing”, e.g.

Kind regards

robert

Robert K.:

irb(main):010:0> a = []
=> []

[…]

irb(main):015:0> Enumerable === a
=> true

Note that I do not recommend using the test from line 12 as it is
likely much more inefficient than the other ones. The test from line
15 is especially suited for use with “case” statements as in

case a
when Enumerable
puts “it’s enumerable”
when Array, Hash
puts “It’s a special enumerable”
when Integer
puts “You can count on me.”
else
puts “No idea about a.”
end

A minor nitpick: Note that due to case’s behaviour (once a ‘when’
matches, other ‘whens’ are ignored), the above will almost never¹
print ‘It’s a special enumerable’, as Arrays and Hashes are almost
always¹ Enumerable. Testing for Array/Hash first and Enumerable
second would make more sense in most cases.

¹ you can redefine any constant, so you could redefine what
Array and Hash mean, but usually it’s a rather bad idea

— Shot

2010/1/20 Shot (Piotr S.) [email protected]:

Note that I do not recommend using the test from line 12 as it is
else
puts “No idea about a.”
end

A minor nitpick: Note that due to case’s behaviour (once a ‘when’
matches, other ‘whens’ are ignored), the above will almost never¹
print ‘It’s a special enumerable’, as Arrays and Hashes are almost
always¹ Enumerable. Testing for Array/Hash first and Enumerable
second would make more sense in most cases.

Oh, yes of course! Thanks for catching that! The order should have
been reversed.

case a
when Array, Hash
puts “It’s a special enumerable”
when Enumerable
puts “it’s enumerable”
when Integer
puts “You can count on me.”
else
puts “No idea about a.”
end

Thanks again!

Kind regards

robert

On 1/20/2010 12:05 PM, Xeno C. wrote:

type passed in that argument place? What’s the difference between
that and passing a string when it needs say an array?

Nope, that’s an ArgumentError. Example:
irb(main):001:0> Integer(“boo”)
ArgumentError: invalid value for Integer: “boo”
from (irb):2
irb(main):002:0>

Integer(“boo”) syntactically correct, yet “boo” is not a valid argument
for this function.

Robert K. wrote:

First of all that would not be a SyntaxError because the syntax is not
affected. Using this error type will create misleading error
messages.

If I want a method that only takes objects of family Xclass, and I get
one
passed that is not in that family, isn’t that a syntax error? Bad type
passed
in that argument place? What’s the difference between that and passing
a string
when it needs say an array?

irb(main):013:0> a.kind_of? Enumerable
=> true
irb(main):014:0> a.is_a? Enumerable
=> true
irb(main):015:0> Enumerable === a
=> true
irb(main):016:0>

Note that I do not recommend using the test from line 12 as it is
likely much more inefficient than the other ones. The test from line
15 is especially suited for use with “case” statements as in

Thank you. That is the kind of answer I really needed.

Sincerely, Xeno

On 1/20/2010 2:36 PM, Walton H. wrote:

can take an object and go
get one passed that is not in that family, isn’t that a syntax
argument for this function.

Whoops, my bad, actually the situation you describe is a TypeError:
irb(main):002:0> Integer([1,2,3])
TypeError: can’t convert Array into Integer
from (irb):3
irb(main):003:0>

again, still syntactically sound, but Integer can’t take an array.

2010/1/21 Xeno C. [email protected]:

Walton H. wrote:

On 1/20/2010 2:36 PM, Walton H. wrote:

On 1/20/2010 12:05 PM, Xeno C. wrote:

Robert K. wrote:

2010/1/20 Xeno C. [email protected]:

irb(main):001:0> Integer(“boo”)
from (irb):3
irb(main):003:0>

again, still syntactically sound, but Integer can’t take an array.

Okay. Good. Thanks. I appreciate the feedback. This will help my
programming, perhaps semantically I guess I should say.

Actually I would be less strict about the question whether a
TypeError, an ArgumentError or a NoMethodError is most appropriate
because I either do not catch any of them or just StandardError. Even
then the important information for me is in the stack trace and not so
much in the exception type. But that’s probably because I create
smaller apps with scripting character most of the time. It does make
sense to think about this a little more (but not too much) when
creating larger apps.

I tend to use ArgumentError for wrong arguments because that seems the
most general description of what happened. A NoMethodError will be
thrown automatically when applying Duck Typing (i.e. caused by a
method not understood by the receiver). I’d agree that in this case a
TypeError is probably most appropriate.

Kind regards

robert

Walton H. wrote:

where I
If I want a method that only takes objects of family Xclass, and I
Integer(“boo”) syntactically correct, yet “boo” is not a valid
argument for this function.

Whoops, my bad, actually the situation you describe is a TypeError:
irb(main):002:0> Integer([1,2,3])
TypeError: can’t convert Array into Integer
from (irb):3
irb(main):003:0>

again, still syntactically sound, but Integer can’t take an array.

Okay. Good. Thanks. I appreciate the feedback. This will help my
programming,
perhaps semantically I guess I should say.

Sincerely, Xeno