简体   繁体   English

Ruby Koans 代理项目

[英]Ruby Koans Proxy Project

I'm walking through the Ruby Koans and I have a trouble in about_proxy_object_project.rb我正在浏览 Ruby Koans,但在about_proxy_object_project.rb遇到了麻烦
This is my solution这是我的解决方案

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

but when I typed rake I got this但是当我输入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'

and in my about_proxy_object_project.rb在我的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 

I am confused我很迷惑
Where i did do wrong?我哪里做错了?
Thanks all谢谢大家

and this is my Television class这是我的Television

class Television
  attr_accessor :channel

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

  def on?
    @power == :on
  end
end

In this if clause:在这个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

The check @object.respond_to? method_name检查@object.respond_to? method_name @object.respond_to? method_name always evaluates to true because the Television class defines all these methods you've called on its objects ( channel= , power , channel ). @object.respond_to? method_name计算结果始终为true因为Television类定义了您在其对象( channel=powerchannel )上调用的所有这些方法。 Therefore the first branch of the if runs and this code essentially adds to the @messages instance variable (which is an Array ) the method names that you are calling.因此, if的第一个分支运行并且此代码实质上将您正在调用的方法名称添加到@messages实例变量(这是一个Array )。

So when you call tv.channel the return value of the method is that commented statement in the above code, which of course is not equal to 10 .所以当你调用tv.channel时,该方法的返回值是上面代码中注释的语句,当然不等于10 You essentially get the return value of @messages << method_name which is the new @messages array, which actually contains all the undefined method you've called until that time: [:channel=, :power, :channel] .你基本上得到了@messages << method_name的返回值,它是新的@messages数组,它实际上包含你在那之前调用的所有未定义的方法: [:channel=, :power, :channel]

You can just use 'send' without checking.您可以直接使用“发送”而无需检查。 There is no purpose of using 'else' because it always returns some Exception.使用 'else' 没有任何意义,因为它总是返回一些异常。

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

if you swap the two statements: @object.send(method_name, *args) @messages << method_name # <-- this is the return value you get如果交换两个语句:@object.send(method_name, *args) @messages << method_name # <-- 这是您得到的返回值

so: @messages << method_name # <-- this is the return value you get @object.send(method_name, *args)所以:@messages << method_name # <-- 这是你得到的返回值 @object.send(method_name, *args)

then the return value would be whatever is returned by the method_name, and so in the case of tv.channel it would return 10 as expected in your test.那么返回值将是 method_name 返回的任何值,因此在 tv.channel 的情况下,它将在您的测试中按预期返回 10。

I think this is just saying the same thing as in the answer, but thought it worth making it clearer我认为这只是在说与答案相同的事情,但认为值得更清楚地说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM