読み込み中...

プログラミング初心者でもできる!Rubyのダックタイピング入門10ステップ

プログラミング初心者がRubyのダックタイピングを学ぶイメージ Ruby
この記事は約10分で読めます。

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

本記事のサンプルコードを活用して機能追加、目的を達成できるように作ってありますので、是非ご活用ください。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を満たす現役のプログラマチームによって監修されています。

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

本記事を読めば、プログラミング初心者でもRubyでダックタイピングを使うことができるようになります。

ここでは、具体的なサンプルコードを交えながら、ダックタイピングの基本から応用までを10ステップでご紹介します。

●Rubyとは?

Rubyは、まつもとゆきひろ氏によって開発されたプログラミング言語です。

プログラマの生産性と楽しさを重視した言語設計がなされており、シンプルで直感的な文法や豊富な標準ライブラリなどが特徴です。

●ダックタイピングとは?

ダックタイピングとは、「もし何かがアヒルのように歩き、アヒルのように鳴くなら、それはアヒルだ」という思考法から名付けられました。

プログラミングにおいては、オブジェクトのクラスではなく、そのオブジェクトがどのように振る舞うか(どのメソッドを持っているか)を重視します。

●Rubyでのダックタイピングの基本

Rubyでは、オブジェクト指向の特性としてポリモーフィズム(同一のインターフェースで異なる動作をすること)がありますが、その実現方法としてダックタイピングが使われます。

○サンプルコード1:ダックタイピングの基本形

Rubyでのダックタイピングの基本形を表します。

DogクラスとCatクラスの2つがあり、どちらもtalkというメソッドを持っています。

ここでは、それぞれのクラスのインスタンスを生成し、そのインスタンスに対してtalkメソッドを呼び出します。

class Dog
  def talk
    'ワン!'
  end
end

class Cat
  def talk
    'ニャー!'
  end
end

def animal_talk(animal)
  puts animal.talk
end

dog = Dog.new
cat = Cat.new

animal_talk(dog) # ワン!と出力
animal_talk(cat) # ニャー!と出力

このコードでは、animal_talkメソッドにどちらのクラスのインスタンスを渡しても問題なく動作します。

これがダックタイピングの基本的な考え方です。

●ダックタイピングの使い方

次に、Rubyでダックタイピングをどのように使うのかについて見ていきましょう。

ダックタイピングを使うと、様々な

オブジェクトを同じように扱うことができます。

下記の2つのサンプルコードでは、メソッド内と配列に対するダックタイピングの使い方を見ていきます。

○サンプルコード2:メソッド内でのダックタイピング

次に、メソッド内でのダックタイピングの使用例を示します。

下記のコードでは、動物の鳴き声を出力するanimal_soundメソッドがあります。

このメソッドでは引数に取ったオブジェクトがtalkメソッドを持っていることを期待しています。

class Dog
  def talk
    'ワン!'
  end
end

class Cat
  def talk
    'ニャー!'
  end
end

def animal_sound(animal)
  puts animal.talk
end

animal_sound(Dog.new) # ワン!と出力
animal_sound(Cat.new) # ニャー!と出力

この例では、DogクラスとCatクラスは全く別のクラスですが、どちらもtalkメソッドを持っているため、animal_soundメソッドはどちらのクラスのインスタンスでも適用可能です。

これがダックタイピングの一つの使い方です。

○サンプルコード3:配列に対するダックタイピング

Rubyの配列はどんなオブジェクトでも格納することができます。

そのため、配列の要素に対して一律の操作を行う場合にもダックタイピングを用いることができます。

class Dog
  def talk
    'ワン!'
  end
end

class Cat
  def talk
    'ニャー!'
  end
end

animals = [Dog.new, Cat.new]

animals.each do |animal|
  puts animal.talk
end

このコードでは、DogのインスタンスとCatのインスタンスを配列に格納し、それぞれに対してtalkメソッドを呼び出しています。

どのような動物のインスタンスが配列に入っていても、全てがtalkメソッドを持っていることを期待しているのがわかります。

これもまたダックタイピングの一つの使い方です。

●ダックタイピングの応用例

Rubyのダックタイピングは、その柔軟性からさまざまな応用例があります。

その中でも、動的なメソッド呼び出しとエラーハンドリングの2つのテクニックを紹介します。

○サンプルコード4:動的メソッド呼び出しにダックタイピングを使う

Rubyのオブジェクトはsendメソッドを持っており、これを使うことで動的にメソッドを呼び出すことが可能です。

これは、あるオブジェクトが特定のメソッドを持っていることを期待するダックタイピングと組み合わせると、非常にパワフルなツールとなります。

class Dog
  def talk
    'ワン!'
  end
end

class Cat
  def talk
    'ニャー!'
  end
end

def animal_sound(animal, method)
  puts animal.send(method)
end

animal_sound(Dog.new, :talk) # ワン!と出力
animal_sound(Cat.new, :talk) # ニャー!と出力

上記のコードでは、animal_soundメソッドが2つの引数を取ります。

一つ目の引数は動物のインスタンス、二つ目の引数は呼び出したいメソッドの名前です。

sendメソッドを使うことで、そのメソッド名を動的に決定し、呼び出すことができます。

○サンプルコード5:ダックタイピングを活用したエラーハンドリング

ダックタイピングはエラーハンドリングにも使うことができます。

たとえば、あるメソッドが呼び出せない場合にはエラーメッセージを出力する、といった処理が可能です。

class Dog
  def talk
    'ワン!'
  end
end

class Cat
  def talk
    'ニャー!'
  end
end

class Fish
end

def animal_sound(animal)
  if animal.respond_to?(:talk)
    puts animal.talk
  else
    puts 'この動物は話せません。'
  end
end

animal_sound(Dog.new)  # ワン!と出力
animal_sound(Cat.new)  # ニャー!と出力
animal_sound(Fish.new) # この動物は話せません。と出力

このコードでは、animal_soundメソッドが動物のインスタンスを引数に取り、そのインスタンスがtalkメソッドを持っているかどうかを確認しています。

持っている場合はそのメソッドを呼び出し、持っていない場合はエラーメッセージを出力します。

●ダックタイピングの注意点と対処法

ダックタイピングは非常に便利な技術ではありますが、注意しなければならない点もあります。

まず一つ目は、間違ったメソッド名を呼び出したときにエラーになるという点です。

これは、特定のメソッドの存在を前提としているため、そのメソッドが存在しないオブジェクトに対してダックタイピングを試みるとエラーが発生します。

RubyではこのようなエラーをNoMethodErrorと呼びます。

対処法としては、先程のエラーハンドリングの例のように、呼び出すメソッドの存在チェックを行うことが一つあります。

respond_to?メソッドを使って、オブジェクトがそのメソッドを持っているかどうか確認することができます。

しかし、この方法はすべての場合に適用できるわけではありません。

例えば、複数のメソッドを呼び出すようなコードで、それぞれのメソッドが存在するかを確認するのは面倒な場合があります。

そこで登場するのが、「Nullオブジェクトパターン」です。

Nullオブジェクトパターンは、「何もしない」オブジェクトを定義し、そのオブジェクトに対してメソッド呼び出しを行うことでエラーを防ぐパターンです。

次にそのサンプルコードを見てみましょう。

class NullObject
  def method_missing(name, *args)
    # 何もしない
  end
end

class Dog
  def bark
    'ワン!'
  end
end

def dog_bark(dog = NullObject.new)
  puts dog.bark
end

dog_bark(Dog.new)   # ワン!と出力
dog_bark            # 何も出力しない

このコードではNullObjectクラスを定義しています。

そして、そのクラス内でmethod_missingメソッドを定義しています。

これにより、NullObjectのインスタンスに対して存在しないメソッドが呼び出された場合でも、エラーが発生せずに何もしないようになります。

これにより、dog_barkメソッドの引数が何も渡されなかった場合でも、エラーが発生せずにコードが進行します。

●ダックタイピングのカスタマイズ方法

Rubyのダックタイピングはその柔軟性から様々なカスタマイズが可能です。

その中でも特に有用な方法として、モジュールの活用があります。

モジュールを用いて共通の振る舞いを定義し、それをオブジェクトに取り込むことで、オブジェクトがその振る舞いを持つようになります。

これにより、異なるクラスのオブジェクトでも同じメソッドを呼び出すことが可能になり、ダックタイピングをより効果的に活用することができます。

それでは具体的なサンプルコードとその説明を見てみましょう。

○サンプルコード6:モジュールを活用したダックタイピングのカスタマイズ

module Quackable
  def quack
    'ガーガー!'
  end
end

class Duck
  include Quackable
end

class Robot
  include Quackable
end

duck = Duck.new
robot = Robot.new

puts duck.quack  # => ガーガー!
puts robot.quack  # => ガーガー!

このコードではQuackableというモジュールを定義し、その中にquackメソッドを定義しています。

そして、DuckクラスとRobotクラスにそのモジュールを取り込むことで、両クラスのオブジェクトがquackメソッドを呼び出すことが可能になります。

この結果、異なるクラスのオブジェクトでも同じメソッドを呼び出すことが可能となり、ダックタイピングの恩恵を受けることができます。

ここまでRubyのダックタイピングについて詳しく見てきましたが、その本質はオブジェクトがどのクラスに属しているかではなく、どのように振る舞うかに注目することです。

そしてその振る舞いはメソッドとして表現されます。

この考え方はRubyだけでなく、オブジェクト指向プログラミング全般に通じるものであり、理解しておくことでより柔軟なコード設計が可能となります。

まとめ

プログラミング初心者でも扱うことのできるRubyのダックタイピングについて、具体的なサンプルコードを交えて解説しました。

Rubyにおけるダックタイピングは非常に強力なツールであり、オブジェクトの振る舞いに注目することで柔軟なコード設計が可能です。

また、エラーハンドリングやモジュールの活用といった対処法やカスタマイズ方法についても紹介しました。

これらの知識を活用することで、あなたもRubyのプログラミングスキルを一段と深めることができるでしょう。

プログラミングは絶えず新しい学びがあり、その一つ一つがあなたのスキルを高めてくれます。

これからも新しい知識を身につけて、より多様で柔軟なコードを書く能力を高めていきましょう。