如何在Ruby中引用同一个类的另一个对象?

时间:2015-07-03 16:36:34

标签: arrays ruby object containers

我想基于Ruby数组为对象创建容器类。我想操纵这些容器中的多个容器,例如将2个连接在一起。如果我试试这个:

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 )

我收到错误:

  

append': undefined method每个'对于#(NoMethodError)来自./test.rb:40:in`'

我尝试过不同的方法,比如创建一个看似想要的方法,但到目前为止还没有运气。有什么建议?并提前感谢!

3 个答案:

答案 0 :(得分:2)

如果您希望能够将Things添加到Things,则您有两种能力:要么在Things上实现迭代器方法,要么只是装饰包裹Array:< / p>

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 :(得分: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

答案 2 :(得分: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. 在此上下文中添加了一种新方法+