有没有一种方法可以使变量的仅一个类从另一类继承?

时间:2020-08-23 00:01:39

标签: ruby class inheritance

我是新手,也许我在搜索中错过了一些内容,但是我浏览了文档以及此处的其他问题,但没有找到问题的答案,因此,请把它放在这里,如果对不起,请原谅它已经在其他地方进行了解释。 我在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

所以它会导致类似这样的结果:

  1. 我创建了一个动物“套件”,是“猫”家族中年龄7岁的“猫”。
  2. 有一个Animal_Group实例,名为“猫科动物”,变量@lifespan ='17',@ environment_sphere ='terrestrial'和@breed_max ='6'
  3. 'kit'将使它们具有变量,其值如下:
@ident = 'kit'
@species = 'cat'
@family = 'feline'
@age = '7'
@lifespan = '17'
@environment_sphere = 'terrestrial'
@breed_max = '6'

有没有办法做到这一点,或者唯一的办法就是将所有内容都转换为新类?

2 个答案:

答案 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的值。

使用ObjectSpace::each_object

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