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.
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
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):
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.
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
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
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?
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.
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.
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.
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
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.