如何在 Ruby 中引用同一 class 的另一个对象?
How do I reference another object of the same class in Ruby?
我想为基于 Ruby 数组的对象创建容器 class。我想操纵这些容器中的多个容器,比如将 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 )
我收到错误:
in append': undefined method
each' for # (NoMethodError) from ./test.rb:40:in `'
我尝试过不同的方法,例如创建一个似乎需要的 each 方法,但到目前为止还没有成功。有什么建议么?提前致谢!
如果你希望能够将Things
添加到Things
,你有两个能力:要么在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
我想应该有一个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">]
考虑这种方法:
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">]>
备注:
- 稍微修改了 API 以简化代码。
- 添加了一个新方法
+
作为其在此上下文中的直观方法。
我想为基于 Ruby 数组的对象创建容器 class。我想操纵这些容器中的多个容器,比如将 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 )
我收到错误:
in
append': undefined method
each' for # (NoMethodError) from ./test.rb:40:in `'
我尝试过不同的方法,例如创建一个似乎需要的 each 方法,但到目前为止还没有成功。有什么建议么?提前致谢!
如果你希望能够将Things
添加到Things
,你有两个能力:要么在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
我想应该有一个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">]
考虑这种方法:
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">]>
备注:
- 稍微修改了 API 以简化代码。
- 添加了一个新方法
+
作为其在此上下文中的直观方法。