Ruby Koans代理项目

时间:2014-03-05 08:20:21

标签: ruby

我正在浏览Ruby Koans,我在about_proxy_object_project.rb中遇到了麻烦 这是我的解决方案

class Proxy
  attr_reader :messages

  def initialize(target_object)
    @object = target_object
    # ADD MORE CODE HERE
    @messages = []
  end

  def number_of_times_called(method_name)
    @messages.count method_name
  end

  def called?(method_name)
    @messages.include? method_name
  end 

  def method_missing(method_name, *args, &block)
    if @object.respond_to? method_name  
      @object.send(method_name, *args)
      @messages << method_name
    else
      super method_name, *args, &block
    end
  end
end

但是当我输入rake时,我得到了这个

The answers you seek...
  Expected 10 to equal [:channel=, :power, :channel]

Please meditate on the following code:
  /home/Shanicky/koans/about_proxy_object_project.rb:61:in `test_tv_methods_still_perform_their_function'

并在我的about_proxy_object_project.rb

def test_tv_methods_still_perform_their_function
  tv = Proxy.new(Television.new)

  tv.channel = 10
  tv.power

  assert_equal 10, tv.channel # this is the 61st line
  assert tv.on?
end 

我很困惑 我做错了什么?
谢谢大家

这是我的Television班级

class Television
  attr_accessor :channel

  def power
    if @power == :on
      @power = :off
    else
      @power = :on
    end
  end

  def on?
    @power == :on
  end
end

3 个答案:

答案 0 :(得分:3)

在这个if条款中:

if @object.respond_to? method_name  
  @object.send(method_name, *args)
  @messages << method_name # <-- this is the return value you get
else
  super method_name, *args, &block
end

支票@object.respond_to? method_name始终评估为true,因为Television类定义了您在其对象(channel=power上调用的所有这些方法, channel)。因此if的第一个分支运行,并且此代码实质上将@messages实例变量(即Array)添加到您正在调用的方法名称中。

因此,当您调用tv.channel时,方法的返回值是上述代码中的注释语句,当然不等于10。你基本上得到@messages << method_name的返回值,它是新的@messages数组,它实际上包含你在此之前调用的所有未定义方法:[:channel=, :power, :channel]

答案 1 :(得分:0)

您可以在不检查的情况下使用“发送”。没有使用'else'的目的,因为它总是返回一些Exception。

def method_missing(method_name, *args, &block)
  @messages << method_name
  @object.send(method_name, *args, &block)
end

答案 2 :(得分:0)

如果交换两个语句: @object.send(method_name, *args) @messages << method_name # <-- 这是你得到的返回值

所以: @messages << method_name # <-- 这是你得到的返回值 @object.send(method_name, *args)

那么返回值将是 method_name 返回的任何值,因此在 tv.channel 的情况下,它将在您的测试中按预期返回 10。

我认为这只是在说与答案相同的事情,但认为值得更清楚