2015-07-03 111 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

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

相关问题