我试图将摄氏温度转换为华氏温度,反之亦然。如下所示,实例变量@temperature
分别在方法celsius=
和fahrenheit=
中定义。
class Temperature
def self.ctof(temp)
(temp * 9 / 5.0) + 32
end
def self.ftoc(temp)
(temp - 32) * (5 / 9.0)
end
def initialize(options)
if options[:f]
self.fahrenheit = options[:f]
else
self.celsius = options[:c]
end
end
def fahrenheit=(temp)
@temperature = self.class.ftoc(temp)
end
def celsius=(temp)
@temperature = temp
end
def in_fahrenheit
self.class.ctof(@temperature)
end
def in_celsius
@temperature
end
end
这让我感到困惑,因为我从未见过在initialize方法之外定义的实例变量。我希望有人能帮我理解这里发生的事情。
答案 0 :(得分:1)
当您致电Temperature.new(c: 0)
时,这将设置celsius=
访问者,它将实例变量@temperature
(意味着始终以摄氏度为单位)设置为0
。
当您致电Temperature.new(f: 32)
时,会设置fahrenheit=
访问者,将实例变量@temperature
设置为Temperature.ftoc(32)
或0.0
。
调用in_celsius
只会在示例中返回@temperature
或0
。
致电in_fahrenheit
会返回Temperature.ctof(0)
或32.0
。
在构造函数外部定义的实例变量没有什么神奇之处。关键是它是一个在整个实例方法中可用的变量。
答案 1 :(得分:0)
将实例变量设置在initialize
之外是完全正确的。这正是二传手做的事情。您可能已经知道attr_accessor
- 在调用attr_accessor :foo
时,它会为实例变量foo
创建一个getter foo=
和一个setter @foo
,即两个等效的方法:
def foo
@foo
end
def foo=(value)
@foo = value
end
在您的代码中,in_celsius
和celsius=
就是这样:@temperature
的getter和setter。
但是你的代码确实看起来有点复杂。我认为这是因为Temperature
必须处理华氏度和摄氏度。您可以通过为每个温度范围提供单独的类来简化它:
class Celsius
attr_reader :value
def initialize(value)
@value = value
end
def to_celsius
self
end
def to_fahrenheit
Fahrenheit.new((value * 9 / 5.0) + 32)
end
end
class Fahrenheit
attr_reader :value
def initialize(value)
@value = value
end
def to_celsius
Celsius.new((value - 32) * (5 / 9.0))
end
def to_fahrenheit
self
end
end
现在每个类都有一个实例变量@value
,它在initialize
内设置。
temperature = Celsius.new(0)
#=> #<Celsius:0x007fb83d8b33a8 @value=0>
temperature.to_fahrenheit
#=> #<Fahrenheit:0x007fb83d8b3128 @value=32.0>