変数の1つのクラスだけを別のクラスから継承させる方法はありますか?
私は初心者で、検索で何かを見逃したかもしれませんが、ここでドキュメントやその他の質問を調べましたが、質問の答えが見つかりませんでした。ここに入れて、すでにある場合は失礼します。他の場所で説明しました。ルビーには2つのクラスがあります。1つはAnimalと呼ばれ、もう1つは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
したがって、次のような結果になります。
- 「猫」科の「7歳」の「猫」である動物「キット」を作成します。
- 変数@ lifespan = '17'、@ environment_sphere = 'terrestrial'、および@breed_max = '6'を持つ 'feline'というAnimal_Groupのインスタンスがあります。
- 'kit'には、次のような変数と値があります。
@ident = 'kit' @species = 'cat' @family = 'feline' @age = '7' @lifespan = '17' @environment_sphere = 'terrestrial' @breed_max = '6'
それを行う方法はありますか、それともすべてを新しいクラスに変える唯一の方法はありますか?
回答
基本的に、メタプログラミングがなければ、これは不可能です。メタプログラミングでそれを行う方法を示すことはできますが、それを読者に練習として残しておきます。なぜなら、それについて言えば、物事を単純に保つ方が良いので、間違いなくもっと簡単な方法があるからです。
とにかく、私がお勧めするのは次のようなシステムです:
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
これは、書きたいコードよりも少し柔軟性が低いように見えるかもしれないことを理解しています。動物グループの「タイプ」を動的インスタンス変数として格納する代わりに、基本的にクラス定義を使用してハードコーディングしています。しかし、うまくいけば、このアプローチがいかに簡単であるかがわかるでしょう。
仮定します
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
インスタンス変数に値を割り当てるために使用できるアプローチは2つありますAnimal
。両方の場合において、トリックのインスタンスを見つけることであるAnimal_Group
そのinstance_variable@name
値を持つ引数の値と同じfamily
にしますAnimal.new
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">