例如,我有一个包含@fahrenheit
和@celsius
实例变量的Temperature类。
我还有两种转换温度的方法in_fahrenheit
和in_celsius
。
使用可以接受选项哈希的构造函数初始化实例变量。
是否有任何可能的方法以某种方式实现方法,以便rspec是
Temperature.new(:f => 212).in_celsius.should == 100
和
Temperature.new(:c => 50).in_celsius.should == 50
该方法可以判断正在访问哪个选项哈希并返回正确的哈希?
我知道的一种方法是删除@fahrenheit
变量,然后根据选项哈希@celsius
a include?
或{ {1}}。
答案 0 :(得分:3)
为什么不使用课程?您可以实现工厂方法并返回Fahrenheit
或Celsius
的实例,具体取决于提供的密钥:
module Temperature
def self.parse(hash)
if hash.has_key? :f
Fahrenheit.new(hash[:f])
elsif hash.has_key? :c
Celsius.new(hash[:c])
end
end
end
用法:
Temperature.parse(f: 212) #=> 212 °F
Temperature.parse(f: 212).in_celsius #=> (100/1) °C
Temperature.parse(c: 50) #=> 50 °C
Temperature.parse(c: 50).in_celsius #=> 50 °C
Temperature.parse(c: 50).in_fahrenheit #=> (122/1) °F
Temperature.parse(c: 100) == Temperature.parse(f: 212) #=> true
我在这里使用rational numbers来避免舍入错误。
上例中使用的Fahrenheit
和Celsius
类的实现:
require 'rational'
module Temperature
class Fahrenheit
attr_reader :value
def initialize(value)
@value = value
end
def ==(other)
value == other.in_fahrenheit.value
end
def in_fahrenheit
self
end
def in_celsius
Celsius.new(Rational(5, 9) * (@value - 32))
end
def inspect
"#{@value.inspect} °F"
end
end
class Celsius
attr_reader :value
def initialize(value)
@value = value
end
def ==(other)
value == other.in_celsius.value
end
def in_fahrenheit
Fahrenheit.new(Rational(9, 5) * @value + 32)
end
def in_celsius
self
end
def inspect
"#{@value.inspect} °C"
end
end
end
答案 1 :(得分:1)
你可以做一些简单的事情
def in_celsius
result = @celsius
result ||= (@fahrenheit - 32 ) * 5.0 / 9
result
end
以及in_fahrenheit
您需要做的唯一事情就是初始化正确的实例变量@celsius
或@fahrenheit
例如
if opts[:f] != nil
@fahrenheit = opts[:f]
elsif opts[:c] != nil
@celsius = opts[:c]
end
答案 2 :(得分:1)
我会做这样的事情,因为我认为一个类应该总是以最简单的格式存储它的数据(在这种情况下是SI单位开尔文)。此外,我喜欢new
方法,它们按预期工作(在这种情况下采用开尔文单位并使用哈希作为后备)。
class Temperatur
attr_accessor :kelvin
def initialize(degree)
if degree.is_a?(Numeric)
@kelvin = kelvin
else
@kelvin = from_celsius(args[:c]) || from_fahrenheit(args[:f])
end
end
def fahrenheit
@kelvin * 1,8 - 459,67
end
def celsius
@kelvin + 273,15
end
private
def from_fahrenheit(fahrenheit)
if fahrenheit
(fahrenheit.to_f + 459,67) * 5 ⁄ 9
end
end
def from_celsius(celsius)
if celsius
celsius.to_f - 273,15
end
end
end