想象一下以下代码:
class SimpleLetter
def values
("a" .. "z").to_a
end
def ===(other)
values.include?(other)
end
end
class Vowel < SimpleLetter
def values
["a","e","i","o","u"]
end
end
class Consonant < SimpleLetter
def values
super - Vowel.new.values
end
end
objects = ("a" .. "f").to_a + (1 .. 5).to_a
objects.each do |letter|
case letter
when Vowel.new
puts "#{letter} it's a vowel"
when Consonant.new
puts "#{letter} it's a consonant"
else
puts "#{letter} it's something else"
end
end
我可以选择任何其他类,我只是以它们为例。我非常喜欢Scala的match
和提取器,我认为这可能是在Ruby中编写相同内容的好方法。是否有更好的方法来编写上述内容而不必实例化新对象,这样我就可以调用他们的===
方法?
为了避免不必要的帖子,是的,我知道我可以这样做:
case letter
when ["a","e","i","o","u"].include?(letter)
# ...
end
答案 0 :(得分:5)
您不需要角色类。将它们设置为数组,并在case语句中使用splat运算符。
SimpleLetter = ("a" .. "z").to_a
Vowel = %w[a e i o u]
Consonant = SimpleLetter - Vowel
(("a" .. "f").to_a + (1 .. 5).to_a).each do |letter|
case letter
when *Vowel
puts "#{letter} it's a vowel"
when *Consonant
puts "#{letter} it's a consonant"
else
puts "#{letter} it's something else"
end
end
答案 1 :(得分:4)
===
也适用于块:
Letters = ('a'..'z').to_a
Vowels = ['a','e','i','o','u']
Consonants = Letters - Vowels
Vowel = lambda { |x| Vowels.include? x }
Consonant = lambda { |x| Consonants.include? x }
objects = ("a" .. "f").to_a + (1 .. 5).to_a
objects.each do |object|
case object
when Vowel
puts "#{object} is a vowel."
when Consonant
puts "#{object} is a consonant."
else
puts "#{object} is an object."
end
end
答案 2 :(得分:3)
您可以使用类方法而不是实例方法:
class SimpleLetter
def self.values
("a" .. "z").to_a
end
def self.===(other)
values.include?(other)
end
end
class Vowel < SimpleLetter
def self.values
["a","e","i","o","u"]
end
end
class Consonant < SimpleLetter
def self.values
super - Vowel.values
end
end
objects = ("a" .. "f").to_a + (1 .. 5).to_a
objects.each do |letter|
case letter
when Vowel
puts "#{letter} it's a vowel"
when Consonant
puts "#{letter} it's a consonant"
else
puts "#{letter} it's something else"
end
end
答案 3 :(得分:2)
你困惑我的代码,因为SimpleLetter
应该是一个字母,而不是整个字母。
尽管monkeypatching有点风险,但我还是有一半想做以下事情:
module Voweliness
def vowel?
self =~ /[aeiou]/i
end
def consonant?
(self =~ /[a-z]/i and not vowel?)
end
end
class String
include Voweliness
end
objects.each do |letter|
case
when letter.vowel?
puts "#{letter} is a vowel"
when letter.consonant?
puts "#{letter} is a consonant"
else
puts "#{letter} is something else"
end
end
答案 4 :(得分:1)
你已经有几个很好的答案(例如sawa's),所以我在一个没有case
声明的情况下包括一个有趣的答案:
SIMPLE_LETTER = [*"a" .. "z"]
VOWEL = %w[a e i o u]
CONSONANT = SIMPLE_LETTER - VOWEL
[*?a..?f,*1..5].each do |letter|
letter_class = %w(vowel consonant).select { |c| Object.const_get(c.upcase).include? letter}.first
puts "'#{letter}': #{ letter_class || "something else"}"
end
输出:
'a': vowel
'b': consonant
'c': consonant
'd': consonant
'e': vowel
'f': consonant
'1': something else
'2': something else
'3': something else
'4': something else
'5': something else
多splat和字符文字仅适用于1.9。