我是新手,也许我在搜索中错过了一些内容,但是我浏览了文档以及此处的其他问题,但没有找到问题的答案,因此,请把它放在这里,如果对不起,请原谅它已经在其他地方进行了解释。 我在ruby中有两个类,一个叫做Animal,另一个是Animal_Group。在Animal的初始化中,我有一个名为@family的变量,我想将此变量与Animal_Group的现有实例进行比较,如果有匹配项,我希望它继承定义(包括Animal_Group类的值初始化)变量本身)类Animal_Group及其实例。
只是说明一下,就像这样:
class Animal
def initialize(ident, species, family, age)
@ident = ident
@species = species
@family = family
if family.class == Animal_Group
super(*args)
end
@age = age
end
end
所以它会导致类似这样的结果:
@ident = 'kit' @species = 'cat' @family = 'feline' @age = '7' @lifespan = '17' @environment_sphere = 'terrestrial' @breed_max = '6'
有没有办法做到这一点,或者唯一的办法就是将所有内容都转换为新类?
答案 0 :(得分:1)
基本上,没有元编程,那么这是不可能的。尽管我可以展示如何使用元编程来做到这一点,但我会将其作为练习留给读者,因为当涉及到它时,最好使事情保持简单,并且肯定有一种更简单的方法。
无论如何,我推荐的系统是这样的:
class AnimalGroup
attr_reader :lifespan, :environment_sphere, :breed_max, :age
end
class Feline < AnimalGroup
def initialize
@lifespan = '17'
@environment_sphere = 'terrestrial'
@breed_max = '6'
end
end
class Cat < Feline
def initialize(age)
@age = age
super
end
end
我知道这似乎比您要编写的代码灵活一些。与其将动物组的“类型”存储为动态实例变量,我们基本上是使用类定义对其进行硬编码。但希望您能看到这种方法更简单。
答案 1 :(得分:0)
假设
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">
我假设family
中参数Animal.new
的实例将是'Boots'
或'Hank'
,如
Animal.new('kit', 'Hank', 7)
如果我误解了这个问题,没有理由进一步阅读。
可以使用两种方法来使用Animal_Group
实例中的信息来为Animal
实例的实例变量分配值。在这两种情况下,诀窍都是要找到{_1}}实例,其instance_variable Animal_Group
的值等于@name
family
的值。
Animal.new
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