2

我正在经历 Test First 的 Ruby 项目,并且我已经完成了大部分项目,但是 08_temperature_object 让我很困惑,尤其是因为即使我已经让它工作通过了测试,但我不确定我是否按照他们想要的方式做.

这是我想出的:

class Temperature
    def initialize(options = {})
        @options = options
        #@options = Hash.new { |h, key| h[key] = [] }
    end
    #end

    def in_fahrenheit
        @options.key?(:f) ? @options[:f] : (@options[:c] * 9.0 / 5) + 32
    end

    def in_celsius
        @options.key?(:c) ? @options[:c] : (@options[:f] - 32) * 5.0 / 9
    end

    def self.from_fahrenheit(num)
        self.new(:f => num)
    end

    def self.from_celsius(num)
        self.new(:c => num)
    end
end

class Celsius < Temperature

    def initialize(num, options = {})
        @options = options
        @options[:c] = num
    end

    def in_fahrenheit
        super
    end

    def in_celsius
        super
    end
end

class Fahrenheit < Temperature

    def initialize(num, options = {})
        @options = options
        @options[:f] = num
    end

    def in_fahrenheit
        super
    end

    def in_celsius
        super
    end
end

根据说明:

请记住将from_celsius工厂方法定义为方法,而不是实例方法。

???我是作为一个类方法来做的吗?有没有比创建新对象更好的方法?

温度对象的构造函数应接受包含条目或条目的选项散列:celcius:fahrenheit

???我知道我使用了散列,但我使用了“选项散列”吗?

工厂方法是一种设计模式......在 Ruby 中实现这种模式的一种方法是通过类方法

???这是写成工厂方法吗?

以下是 Rspec 测试的一些示例供参考:

describe Temperature do

  describe "can be constructed with an options hash" do
    describe "in degrees fahrenheit" do
      it "at 50 degrees" do
        Temperature.new(:f => 50).in_fahrenheit.should == 50
      end

 describe "can be constructed via factory methods" do

    it "in degrees celsius" do
      Temperature.from_celsius(50).in_celsius.should == 50
      Temperature.from_celsius(50).in_fahrenheit.should == 122
    end

  # test-driving bonus:
  #
  # 1. make two class methods -- ftoc and ctof
  # 2. refactor to call those methods from the rest of the object
  #
  # run *all* the tests during your refactoring, to make sure you did it right
  #
  describe "utility class methods" do

  end

  # Here's another way to solve the problem!
  describe "Temperature subclasses" do
    describe "Celsius subclass" do
      it "is constructed in degrees celsius" do
        Celsius.new(50).in_celsius.should == 50
        Celsius.new(50).in_fahrenheit.should == 122
      end

      it "is a Temperature subclass" do
        Celsius.new(0).should be_a(Temperature)
      end
    end

提前致谢

4

1 回答 1

4

???我是作为一个类方法来做的吗?

是的

有没有比创建新对象更好的方法?

并非如此,这看起来像是本课的预期结果。

温度对象的构造函数应该接受一个包含 :celcius 条目或 :fahrenheit 条目的选项散列。

???我知道我使用了散列,但我使用了“选项散列”吗?

是的,有点

在构造之后保留选项散列,并在所有计算中引用它可能不是最简单的解决方案。在内部,您可以/应该有一个温度的数字实例变量。甚至可能是开尔文。

子类的使用意味着它们在适当的单元中保留一个内部变量(尽管这不是必需的,但测试的重点是驱动公共接口行为,在很大程度上你可以自由地实现你认为合适的内部)

在某些情况下可以做一些您在帖子中所做的事情(例如正确地往​​返数据或延迟转换),并且测试场景非常简单,因此您选择的结果很难判断任何一种方式。所以你可能会得到其他意见。

您所做的最大问题是:

hash = { :c => 25 }
t = Temperature.new( hash )

# This reaches inside the new object and changes its state, breaking encapsulation:
hash[:c] = 30

工厂方法是一种设计模式......在 Ruby 中实现这种模式的一种方法是通过类方法

???这是写成工厂方法吗?

是的

工厂方法只是返回一个新的、有效的、正确初始化的对象的方法。

于 2013-04-04T22:03:53.237 回答