1
0

More than 1 year has passed since last update.

僕も Ruby で ポリモーフィズム やってみた

Last updated at Posted at 2021-12-05

はじめに

前回の記事 Ruby 多重継承 Mix-in でクラスの継承が気になっていたところ ポリモーフィズムの記事 がありましたので、やってみました。

継承版

class Animal
  def cry(voice: '')
    puts "#{voice}"
  end
end

class Dog < Animal
  def cry(voice: 'わんわん')
    super
  end
end

class Cat < Animal 
  def cry (voice: 'にゃー')
    super
  end
end

Dog.new.cry
Cat.new.cry

流石にもろコピペは回避いたしましたが、Javaで散々やったパターンです。

合成ダックタイピング

class Animal
  def self.cry(animal)
    puts animal.cry
  end
end

class Dog
  def cry(voice: 'わんわん')
    voice
  end
end

class Cat
  def cry (voice: 'にゃー')
    voice
  end
end

Animal.cry(Dog.new)
Animal.cry(Cat.new)

発想の転換なのかわかりませんが、継承版の方はメソッド側が変化しているのに対し、合成ダック版はオブジェクト側が変化しています。
でも、これの分岐テストってどうやるんでしょうね。

module Animal
  def self.cry(animal)
    if animal.instance_of?(Dog)
      puts 'わんわん'
    elsif animal.instance_of?(Cat)
      puts 'にゃー'
    end
  end
end

class Dog; end

class Cat; end

Animal.cry(Dog.new)
Animal.cry(Cat.new)

やっていることは同じだけどダメな例です。
classが増えるたびにelsifを追加する必要があるけど追加忘れしたりするパターンです。
合成ダック版はclass Animalを触る必要がないところが素晴らしいです。

class AnimalCry
  def cry(Dog)
    puts 'わんわん'
  end
  def cry(Cat)
    puts 'わんわん'
  end
end

class Dog; end

class Cat; end

AnimalCry.new.cry(Dog.new)
AnimalCry.new.cry(Cat.new)

C#だったらこんな感じで通ったような気がします。
引数の型や数を変化させることで同じメソッドが設定できたはず。
Ruby だと通りませんが。

ダックタイピングって今一理解できなかったのですが、ポリモーフィズムの観点で掴めた様な気がします。
コメント欄にて、@obelisk68 さんと @kts_h さんにいろいろとアドバイスいただき、ありがとうございました。

継承と合成で参照した記事
Goやるなら知っておきたい「Composition over inheritance」

まとめ

  • @kat0 さん、ありがとう
  • OOPに詳しくなった
1
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0