【Ruby】ポリモーフィズムとは?〜継承とダックタイピング〜

Ruby
記事内に広告が含まれています。

はじめに

この記事では、オブジェクト指向の基本である ポリモーフィズム(多態性) を継承とダックタイピングの方法で説明し、それぞれの考え方の違いにも触れていきます。

ポリモーフィズムとは?

ポリモーフィズムとは、異なるクラスのオブジェクトが、同じメソッド名で異なる振る舞いをすることです。
Rubyでは、継承とダックタイピングの2つの代表的な方法でこれを実現できます。

継承によるポリモーフィズム

親クラスを使って振る舞いを統一する実装パターンです。

class Animal
  def speak
    raise NotImplementedError
  end
end

class Dog < Animal
  def speak
    "ワン!"
  end
end

class Cat < Animal
  def speak
    "ニャー!"
  end
end

[Dog.new, Cat.new].each do |animal|
  puts animal.speak
end
# 実行結果:
# ワン!
# ニャー!

Animalspeak という共通のインターフェースを定義。
DogCat はそれを実装。
each で統一的に処理できるのは、すべてのオブジェクトが Animal を継承しているからです。

ダックタイピングによるポリモーフィズム

この方法では、共通の親クラスは必要ありません。

「もしもそれがアヒルのように歩き、アヒルのように鳴くのなら、それはアヒルに違いない」
(If it walks like a duck and quacks like a duck, it must be a duck)

Rubyではこのように、クラスの継承関係よりも「何ができるか」に注目するスタイルをダックタイピングと呼びます。
たとえば、speak というメソッドを持っていれば、どんなクラスでも同じように扱えます。

class Dog
  def speak
    "ワン!"
  end
end

class Cat
  def speak
    "ニャー!"
  end
end

[Dog.new, Cat.new].each do |animal|
  puts animal.speak
end
# 実行結果:
# ワン!
# ニャー!

このように、DogCatspeak メソッドを持っているため、同じように扱うことができます。
クラスの継承関係は必要ありません。「speak できるか?」がすべてです。

継承とダックタイピングの違い

一見すると、「ダックタイピングはAnimalの継承がないだけ?」と思えるかもしれません。
ですが、実は設計の思想がまったく異なります。

継承:型で振る舞いを保証する設計

class Animal
  def speak
    raise NotImplementedError
  end
end

共通の親クラスでメソッドの存在を明示的に保証。
保守性が高く、型(親クラス)に基づいて設計が統一されます。

ダックタイピング:「できること」で判断する設計

Rubyでは、クラスに関係なく speak メソッドを持っていれば、それを「鳴けるもの」として扱います。
このように、「型」ではなく「振る舞い」で判断するのがダックタイピングです。

最後に

Rubyにおけるポリモーフィズムの実現方法として「継承」と「ダックタイピング」の2つを説明してきました。
どちらのパターンでも、DogCat など異なるクラスのオブジェクトが、同じ speak というメソッド名で異なる振る舞いをしていたのを覚えているでしょうか?
このように、異なる型のオブジェクトが同じメソッドを呼び出されても、それぞれのやり方で振る舞うことが、ポリモーフィズムです。

最後までお読みいただきありがとうございました。

皆さんからのコメントやSNSでのシェア、嬉しい投稿をいただくと本当に励みになります。

もしこの記事が気に入ったら感想をコメントやSNSでシェアしていただけると嬉しいです。

皆さんの声を聞かせてくださいね!

Ruby
tetsuをフォローする
簿記はじめるってよ

コメント

タイトルとURLをコピーしました