Hi, easy example of what I need:
klass = String
case klass
when String
puts “I’m String class”
else
puts “I’m nothing…”
end
It produces “I’m nothing…”. I understand why:
“case” matches the given object using “===”, and:
String === String
=> false
while:
String === “a new string”
=> true
But in my case, klass variable holds a class rather than a class
instance. How could I use it within the above “case” statement? The
only way I’ve found is:
klass = String
case klass.name
when “String”
puts “I’m String class”
else
puts “I’m nothing…”
end
I don’t think there’s a better solution than what you already have.
There are different ones, of course - good ol’ if…elsif…else chain,
a hash with classes being its keys ({String=>“I’m String class”,
Fixnum=>“I’m an integer”}[klass] || “I’m nothing”) - but I wouldn’t
say they are better.
Maybe something else could be redone? Where does that class come from?
– Matma R.
2011/8/14 Bartosz Dziewoński removed_email_address@domain.invalid:
I don’t think there’s a better solution than what you already have.
There are different ones, of course - good ol’ if…elsif…else chain,
a hash with classes being its keys ({String=>“I’m String class”,
Fixnum=>“I’m an integer”}[klass] || “I’m nothing”) - but I wouldn’t
say they are better.
Maybe something else could be redone? Where does that class come from?
I need “klass” to hold a class name, not an instance. That cannot be
changed.
Thanks.
2011/8/14 Chris W. removed_email_address@domain.invalid:
end
You could also modify it to accept a variable number of arguments to check
against multiple classes in a single when statement:
false
end
This form works with a single class as well.
Really great, thanks a lot.
end
It produces “I’m nothing…”. I understand why:
“case” matches the given object using “===”, and:
String === String
=> false
Correct, because triple equals checks to see if the value is an instance
or subclass of a class, not if it’s the actual class itself
while:
String === “a new string”
=> true
Which is why this works. One way to potentially get around this is to
have an object that simple holds a class and overrides the === operator
to make case work properly:
class ClassCheck
def initialize(klass)
@holder = klass
end
def ===(other)
@holder == other
end
end
klass = String
case klass
when ClassCheck.new(String)
puts “String”
else
puts “Nothing”
end
You could also modify it to accept a variable number of arguments to
check against multiple classes in a single when statement:
class ClassCheck
def initialize(*klass)
@holder = klass
end
def ===(other)
@holder.each { | klass |
return true if klass == other
}
false
end
end
klass = String
case klass
when ClassCheck.new(Object, Numeric, String)
puts “One of these”
else
puts “Nothing”
end
This form works with a single class as well.
Regards,
Chris W.
http://www.twitter.com/cwgem
On Aug 14, 2011, at 09:26 , Chris W. wrote:
def ===(other)
@holder.each { | klass |
return true if klass == other
}
false
end
def === o
@holder.any? { |k| k == o }
end
On Aug 14, 2011, at 08:47 , Iaki Baz C. wrote:
klass = String
case klass
when String
puts “I’m String class”
else
puts “I’m nothing…”
end
case
when String == klass then
…
else
…
end
or to do a much cleaner version of the multi-match example above:
case
when [String, Whatever].include? klass then
…
else
…
end
2011/8/15 Ryan D. removed_email_address@domain.invalid:
case
when [String, Whatever].include? klass then
…
else
…
end
The most ellegant way. Thanks.
“Iñaki Baz C.” removed_email_address@domain.invalid wrote in post #1016614:
But in my case, klass variable holds a class rather than a class
instance. How could I use it within the above “case” statement? The
only way I’ve found is:
klass = String
case klass.name
when “String”
puts “I’m String class”
else
puts “I’m nothing…”
end
As you’ve found, Class#=== tells you if an object in an instance of a
class
(like is_a?), and this is how it’s intended to be used.
You could in some cases make an instance (as long as the initializer
doesn’t need any arguments):
case klass.new
when String
puts “I’m a String”
end
But case is really intended for ‘matches’ tests. If you want ‘equal to’,
then maybe you’re better off with a simple Hash.
KLASS_LOOKUP = {
String => lambda { puts “I’m a String” },
}
KLASS_LOOKUP.default = lambda { puts “Something else” }
klass = String
KLASS_LOOKUP[klass].call