Ruby练习三

Q1: attr_accessor_with_history

attr_accessor uses metaprogramming to create getters and setters for object attributes on the fly. Define a method attr_accessor_with_history that provides the same functionality as attr_accessor but also tracks every value the attribute has ever had:

class Foo attr_accessor_with_history :bar end f = Foo.new # => #<Foo:0x127e678> f.bar = 3 # => 3 f.bar = :wowzo # => :wowzo f.bar = 'boo!' # => 'boo!' f.bar_history # => [nil, 3, :wowzo, 'boo!']

> Here are some hints and things to notice to get you started:
1. The first thing to notice is that if we define attr_accessor_with_history in class Class, we can use it as in the snippet above. This is because in Ruby a class is simply an object of class Class.
2. The second thing to notice is that Ruby provides a method class_eval that takes a string and evaluates it in the context of the current class, that is, the class from which you're calling attr_accessor_with_history.  This string will need to contain a method definition that implements a setter-with-history for the desired attribute attr_name.
3. bar_history should always return an Array of elements, even if no values have been assigned yet.
4. Don't forget that the very first time the attribute receives a value, its history array will have to be initialized.
5. Don't forget that instance variables are referred to as @bar within getters and setters.
6. Although the existing attr_accessor can handle multiple arguments (e.g. attr_accessor :foo, :bar), your version just needs to handle a single argument.  However, it should be able to track multiple instance variables per class, with any legal class names or variable names, so it should work if used this way:
7. History of instance variables should be maintained separately for each object instance. that is, if you do:

> ```ruby
class SomeOtherClass attr_accessor_with_history :foo
    attr_accessor_with_history :bar
end

f = Foo.new f.bar = 1 f.bar = 2 f = Foo.new f. bar = 4 f.bar_history

> then the last line should just return [nil,4], rather than [nil,1,2,4]. Here is some skeleton code:

> ```ruby
class Class
 def attr_accessor_with_history(attr_name)
   attr_name = attr_name.to_s   # make sure it's a string
   attr_reader attr_name        # create the attribute's getter
   attr_reader attr_name+"_history" # create bar_history getter
   class_eval "your code here, use %Q for multiline strings"
 end
end

class Foo attr_accessor_with_history :bar end f = Foo.new f.bar = 1 f.bar = 2 f.bar_history # => if your code works, should be [nil,1,2]

####My Example Code

```ruby
class Class
    def attr_accessor_with_history(attr_name)
        attr_name = attr_name.to_s
        attr_reader attr_name
        attr_reader attr_name + "_history"

        #our setter code here
        class_eval %Q{
            def #{attr_name}=(attr_name)
                @#{attr_name} = attr_name

                unless @#{attr_name + "_history"}
                    @#{attr_name + "_history"} = []
                    @#{attr_name + "_history"} << nil
                end
                @#{attr_name + "_history"} << attr_name
            end
        }
    end
end

class Test
    attr_accessor_with_history :sample
end

t = Test.new
t.sample = "test"
t.sample = 1
t.sample = :abc
print t.sample_history

Q2: Extend Currency Conversion Example

Extend the currency-conversion example from the text so that you can write: 5.dollars.in(:euros), 10.euros.in(:rupees)

You should support the currencies 'dollars', 'euros', 'rupees', and 'yen' where the conversions are: 1 rupee to 0.019 dollars, 1 yen to 0.013 dollars, 1 euro to 1.292 dollars.

Both the singular and plural forms of each currency should be acceptable, e.g. 1.dollar.in(:rupees) and 10.rupees.in(:euro) should work. You can use the code below (http://pastebin.com/agjb5qBF) as a starting point.

class Numeric @@currencies = {'yen' => 0.013, 'euro' => 1.292, 'rupee' => 0.019} def method_missing(method_id) singular_currency = method_id.to_s.gsub( /s$/, '') if @@currencies.has_key?(singular_currency) self * @@currencies[singular_currency] else super end end end

####My Example Code
```ruby
class Numeric
    @@currencies = {'dollar' => 1.000,'yen' => 0.013, 'euro' => 1.292, 'rupee' => 0.019}
    
    def method_missing(method_id)
        sigular_currency = method_id.to_s.gsub(/s$/,'')
        if @@currencies.has_key?(sigular_currency)
            self * @@currencies[sigular_currency]
        else
            super
        end
    end

    def in(currency)
        sigular_currency = currency.to_s.gsub(/s$/,'')
        self / @@currencies[sigular_currency]       
    end

end

puts 5.dollars.in(:euros)
puts 10.euros.in(:rupees)

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏我和未来有约会

简练的视图模型 ViewModel

patterns & practices Developer Center 发布了 Unity Application Block 1.2 for Silver...

2159
来自专栏linux驱动个人学习

高通msm8909耳机调试

1、DTS相应修改: DTS相关代码:kernel/arch/arm/boot/dts/qcom/msm8909-qrd-skuc.dtsi: 1 s...

7385
来自专栏Netkiller

以太坊 Iban 地址

中国广东省深圳市龙华新区民治街道溪山美地 518131 +86 13113668890 <netkiller@msn.com>

40416
来自专栏搞前端的李蚊子

Html5模拟通讯录人员排序(sen.js)

// JavaScript Document  var PY_Json_Str = ""; var PY_Str_1 = ""; var PY_Str_...

5866
来自专栏MelonTeam专栏

Bitmap 源码阅读笔记

导语: Android 系统上的图片的处理,跟Bitmap 这个类脱不了关系,我们有必要去深入阅读里面的源码,以便在工作中能更好的处理Bitmap相关的问题...

2458
来自专栏跟着阿笨一起玩NET

c# 使用timer定时器操作,上次定时到了以后,下次还未执行完怎么处理

------解决方案-------------------------------------------------------- 开始的时候,禁用定时器,你...

2571
来自专栏linux驱动个人学习

高通Audio中ASOC的machine驱动

ASoC被分为Machine、Platform和Codec三大部分,其中的Machine驱动负责Platform和Codec之间的耦合以及部分和设备或板子特定的...

9664
来自专栏专知

2018年SCI期刊最新影响因子排行,最高244,人工智能TPAMI9.455

2018年6月26日,最新的SCI影响因子正式发布,涵盖1万2千篇期刊。CA-Cancer J Clin 依然拔得头筹,其影响因子今年再创新高,达244.585...

1272
来自专栏WOLFRAM

向日葵中的数学之美

1823
来自专栏ml

md5算法原理一窥(其一)

    首先,需要了解的事,md5并不是传说中的加密算法,只是一种散列算法。其加密的算法并不是我们说所的那样固定不变,只是一种映射的关系。 所以解密MD5没有现...

3887

扫码关注云+社区