2015-07-03 88 views
0

我想爲基於Ruby數組的對象創建一個容器類。我想操縱這些容器中的多個容器,例如將兩個連接在一起。如果我試試這個:如何引用Ruby中同一類的另一個對象?

class Thing 
    attr_accessor :name 
end 

class Things 
    def initialize 
    @things = Array.new 
    end 

    def addone(a) 
    @things.push(a) 
    end 

    def append(list) 
    list.each { |i| addone(i) } 
    end 
end 

item1 = Thing.new 
item2 = Thing.new 
item3 = Thing.new 
item4 = Thing.new 

item1.name = "Marty" 
item2.name = "Fred" 
item3.name = "Janice" 
item4.name = "John" 

list1 = Things.new 
list1.addone(item1) 
list1.addone(item2) 

list2 = Things.new 
list2.addone(item3) 
list2.addone(item4) 

list3 = Things.new 
list3 = list2.append(list1) 

我得到的錯誤:

in append': undefined method each' for # (NoMethodError) from ./test.rb:40:in `'

我已經嘗試不同的方法,例如創建每種方法,因爲它似乎想要的,但至今沒有運氣。有什麼建議麼?並提前致謝!

回答

2

如果你希望能夠增加ThingsThings,你有兩種能力:要麼落實Things迭代方法或簡單地裝點包裹Array

def append(list) 
    case list 
    when Enumerable then list.each { |i| addone(i) } 
    when Things then list.instance_variable_get(:@things).each { |e| addone(i) } 
    else raise "Sorry, can’t add #{list}" 
end 
+1

我偷懶的辦法:'高清追加(*列表)'再後來'list.flatten.each {...}' – tadman

+0

除非你要能夠存儲陣列:) – mudasobwa

+0

這會破壞數組事情有點,這是真的。好點子! – tadman

1

我想應該有一個getter/setter方法方法:

attr_accessor :things 

那麼你應該改變你的addone方法:

輸出的
def append(list) 
    list.things.each { |i| addone(i) } # iterate through array items, not Things instance object 
    self # return appended list object instead of unchanged provided argument – list1 
end 

list3.things

=> [#<Context::Thing:0x00000001adea48 @name="Janice">, 
    #<Context::Thing:0x00000001ade9f8 @name="John">, 
    #<Context::Thing:0x00000001adea98 @name="Marty">, 
    #<Context::Thing:0x00000001adea70 @name="Fred">] 

Demonstration

1

考慮使用此方法:

class Thing 
    attr_accessor :name 

    def initialize(name) 
    @name = name 
    end 
end 

class Things 
    def initialize(things = []) 
    @things = things 
    end 

    def push(thing) 
    @things.push(thing) 
    end 

    def append(other) 
    @things << other.to_a 
    end 

    def +(other) 
    Things.new(@things + other.to_a) 
    end 

    def to_a 
    @things 
    end 
end 

some_things = %w(Marty Fred Janice John).map { |name| Thing.new(name) } 

things_1 = Things.new 
some_things.first(2).each { |thing| things_1.push(thing) } 

things_2 = Things.new 
some_things.last(2).each { |thing| things_2.push(thing) } 

things_1.append(things_2) # This actually appends to things_1 rather than creating a new object 
new_things = things_1 + things_2 # Creates a new object 

# => #<Things:0x007ff85a1aa770 @things=[ 
# #<Thing:0x007ff85a1aa928 @name="Marty">, 
# #<Thing:0x007ff85a1aa900 @name="Fred">, 
# #<Thing:0x007ff85a1aa8d8 @name="Janice">, 
# #<Thing:0x007ff85a1aa8b0 @name="John">]> 

注:

  1. 稍微修改了API以簡化代碼。
  2. 在此上下文中直觀地添加了一種新方法+
+0

那麼,調用實例方法'append'來掩埋實例,反而提出新的呢?我敢打賭,這段代碼的用戶並不期望這種行爲。 – mudasobwa

+0

是的,它是不好的。已更新,使其更直觀。 –

相關問題