假设
class Animal_Group
attr_reader :name, :lifespan, :breed_mix
def initialize(name, lifespan, breed_mix)
@name = name
@lifespan = lifespan
@breed_mix = breed_mix
end
end
Animal_Group.new("Boots", 18, "Siamese")
#=> #<Animal_Group:0x000056fa3111a878 @name="Boots", @lifespan=18,
# @breed_mix="Siamese">
Animal_Group.new("Hank", 14, "Tabby")
#=> #<Animal_Group:0x000056fa3114f618 @name="Hank", @lifespan=14,
# @breed_mix="Tabby">
我假设Animal.new 中的参数family 的实例将是'Boots' 或'Hank',如
Animal.new('kit', 'Hank', 7)
如果我误解了这个问题,没有理由进一步阅读。
有两种方法可以使用来自Animal_Group 实例的信息来为Animal 实例的实例变量赋值。在这两种情况下,诀窍都是找到Animal_Group 的实例,其instance_variable @name 的值等于Animal.new 中参数family 的值
使用ObjectSpace::each_object
class Animal
def initialize(ident, family, age)
@ident = ident
@family = family
@age = age
family_instance = ObjectSpace.each_object(Object).find do |o|
o.class == Animal_Group && o.name == family
end
# raise exception here if family_instance is nil
@lifespan = family_instance.lifespan
@breed_mix = family_instance.breed_mix
end
end
Animal.new('kit', 'Hank', 7)
#=> #<Animal:0x000056fa31211f10 @ident="kit", @family="Hank",
# @age=7, @lifespan=14, @breed_mix="Tabby">
Animal.new('kat', 'Boots', 4)
#=> #<Animal:0x000056fa31174918 @ident="kat", @family="Boots",
# @age=4, @lifespan=18, @breed_mix="Siamese">
维护Animal_Group的实例列表
class Animal_Group
@name_to_instance = {}
singleton_class.public_send(:attr_reader, :name_to_instance)
attr_reader :name, :lifespan, :breed_mix
def initialize(name, lifespan, breed_mix)
@name = name
@lifespan = lifespan
@breed_mix = breed_mix
self.class.name_to_instance[name] = self
end
end
注意
singleton_class.public_send(:attr_reader, :name_to_instance)
(其中self #=> Animal_Group)为类实例变量@name_to_instance 创建一个读取访问器,该变量包含一个将实例名称映射到实例的散列。
Animal_Group.new("Boots", 18, "Siamese")
#=> #<Animal_Group:0x000056fa311b6110 @name="Boots", @lifespan=18,
# @breed_mix="Siamese">
Animal_Group.new("Hank", 14, "Tabby")
#=> #<Animal_Group:0x000056fa311e9998 @name="Hank", @lifespan=14,
# @breed_mix="Tabby">
注意
Animal_Group.name_to_instance
#=> {"Boots"=>#<Animal_Group:0x000056fa311b6110 @name="Boots",
# @lifespan=18, @breed_mix="Siamese">,
# "Hank"=>#<Animal_Group:0x000056fa311e9998 @name="Hank",
# @lifespan=14, @breed_mix="Tabby">}
class Animal
def initialize(ident, family, age)
@ident = ident
@family = family
@age = age
family_instance = Animal_Group.name_to_instance[family]
# raise exception here if family_instance is nil
@lifespan = family_instance.lifespan
@breed_mix = family_instance.breed_mix
end
end
Animal.new('kit', 'Hank', 7)
#=> #<Animal:0x000056fa311fd9c0 @ident="kit", @family="Hank",
# @age=7, @lifespan=14, @breed_mix="Tabby">
Animal.new('kat', 'Boots', 4)
#=> #<Animal:0x000056fa31212cf8 @ident="kat", @family="Boots",
# @age=4, @lifespan=18, @breed_mix="Siamese">