【Ruby】レッスン5-09:オーバーライドの使い方と基本をマスターしよう

50110130

一つ前のページではファイル操作について学習しました。

今回は オーバーライド について見ていきましょう。

Lesson1:基礎文法編
Lesson2:制御構造編
Lesson3:メソッド編
Lesson4:コレクション編
Lesson5:オブジェクト指向編

 ・Lesson5-1:クラスの基本を理解しよう
 ・Lesson5-2:イニシャライザを理解しよう
 ・Lesson5-3:アクセスメソッドを理解しよう
 ・Lesson5-4:クラス変数とクラスメソッドを理解しよう
 ・Lesson5-5:privateメソッドを理解しよう
 ・Lesson5-6:正規表現を理解しよう
 ・Lesson5-7:クラスの継承を理解しよう
 ・Lesson5-8:ファイル操作を理解しよう
 ・Lesson5-9:オーバーライドを理解しよう ◁今回はココ
 ・Lesson5-10:モジュールを使ってみよう
 ・Lesson5-11:ミックスインを使ってみよう
 ・確認問題5-☆1:モンスター捕獲ゲームを作ろう
 ・確認問題5-☆2:モンスターとの戦闘ゲームを作ろう
 ・確認問題5-☆3:マルバツゲームを作ろう

<<前のページ

Rubyの記事一覧

次のページ>>

Rubyの「オーバーライド」とは

Rubyではオブジェクト指向プログラミングの一環として「オーバーライド」という機能が提供されています。

この機能を使うと親クラスで定義されたメソッドを子クラスで上書きして独自の動作を実装できます。

初心者にとっても、オーバーライドはクラスの柔軟性を高める重要な技術です。

【初心者向け】Rubyのオブジェクト指向を分かりやすくまとめた概念図。 特にクラスの継承、オーバーライド、モジュール、ミックスイン、インスタンス生成の関係性を視覚的に理解できるようまとめている。

オーバーライドの基本とその役割とは

オーバーライドとは、親クラスで定義されているメソッドを子クラスで再定義することを指します。

オーバーライドを使用することで、同じ名前のメソッドでも子クラスでは異なる振る舞いを実装できます。これによりコードの再利用性や拡張性が向上します。

Rubyでは、特にsuperキーワードを使って親クラスのメソッドを部分的に利用することも可能です。

Rubyにおけるオーバーライドの実装例

以下はRubyでオーバーライドを行う具体的なコード例です。

# 親クラスの定義
class Animal
  def speak
    "鳴き声"
  end
end

# 子クラスの定義
class Dog < Animal
  # speakメソッドをオーバーライド
  def speak
    "ワンワン"
  end
end

class Cat < Animal
  # speakメソッドをオーバーライド
  def speak
    "ニャーニャー"
  end
end

# 使用例
dog = Dog.new
puts dog.speak # => "ワンワン"

cat = Cat.new
puts cat.speak # => "ニャーニャー"

この例ではDogおよびCatクラスが親クラスAnimalspeakメソッドをオーバーライドしています。

このように、クラスごとに異なる動作を指定できるのがオーバーライドの強みです。

また、親クラスのメソッドを一部活用したい場合はsuperを使います。

class Dog < Animal
  def speak
    super + "!(元気に鳴いている)"
  end
end

dog = Dog.new
puts dog.speak # => "鳴き声!(元気に鳴いている)"

オーバーライドがもたらす3つのメリット

オーバーライドを使用する主なメリットは以下の通りです:

  1. コードの再利用: 親クラスのメソッドを基に子クラス独自の動作を追加できるため、コードの重複を減らせます。
  2. 柔軟な拡張性: 子クラスで個別の振る舞いを定義できるため、拡張性の高いプログラムを作成できます。
  3. 可読性の向上: 同じ名前のメソッドを使用しつつクラスのコンテキストごとに異なる動作を定義できるため、コードが直感的になります。

学習のまとめと次のステップ

Rubyにおけるオーバーライドは、親クラスから継承したメソッドを再定義することでプログラムの柔軟性と再利用性を向上させる重要な技術です。

この機能を活用することで、より効率的で読みやすいコードを書くことができます。

次の章では、さらにオーバーライドを活用した「モジュール」の応用について学びます。

練習問題|オーバーライドを使って継承理解を深めよう

オーバーライドをしっかりと身に着けるため、練習問題に挑戦しましょう。

オーバーライドを使った実践的な課題に挑戦

親クラスのメソッドを子クラスでオーバーライドする仕組みを学びましょう。

今回作成するコードではVehicleクラスを親クラスとし、CarクラスとBikeクラスを子クラスとして定義します。

親クラスに2つのメソッドを定義し、そのうち1つは子クラスでオーバーライドしましょう。

もう1つのメソッドはオーバーライドせずにそのまま利用します。これを実装してオーバーライドの挙動を理解してください。

以下の要件に従ってコードを完成させてください。

  1. 親クラスVehicleを作成し、以下のメソッドを定義してください:
    • description: “これは乗り物です。”と出力する。
    • type: “この乗り物は一般的なものです。”と出力する。
  2. 子クラスCarVehicleから継承して定義し、以下を実装してください:
    • descriptionメソッドをオーバーライドし、superを利用して「これは乗り物です。」の後に「 車の種類です。」を追加して出力する。
  3. 子クラスBikeVehicleから継承して定義し、以下を実装してください:
    • descriptionメソッドを完全にオーバーライドし、「これはバイクです。」と出力する。
  4. 子クラスCarBikeでは、親クラスのtypeメソッドをそのまま使用する。
  5. それぞれのインスタンスを作成し、descriptiontypeメソッドを呼び出して結果を確認する。

ただし、以下のような実行結果となること。

これは乗り物です。
この乗り物は一般的なものです。
これは乗り物です。 車の種類です。
この乗り物は一般的なものです。
これはバイクです。
この乗り物は一般的なものです。

【ヒント】自力で解くのが難しい人へ

1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。

Q
ヒント1【コードの構成を見る】

正解のコードは上から順に以下のような構成となっています。
(※下記の□はコード内のインデントを表しています)

1:Vehicleクラスの定義
  □ descriptionメソッドの定義
  □ □ ”これは乗り物です。”という文字列を返す
  □ typeメソッドの定義
  □ □ ”この乗り物は一般的なものです。”という文字列を返す
2:Carクラスの定義(Vehicleクラスを継承)
  □ 親クラスのdescriptionメソッドをオーバーライド
  □ □ superを使用して親クラスのdescriptionメソッドを呼び出し、” 車の種類です。”を追加して返す
3:Bikeクラスの定義(Vehicleクラスを継承)
  □ 親クラスのdescriptionメソッドをオーバーライド
  □ □ ”これはバイクです。”という新しい文字列を返す
4:Vehicleクラスのインスタンスvehicleを作成
  □ vehicle.descriptionメソッドを呼び出し、戻り値を出力
  □ vehicle.typeメソッドを呼び出し、戻り値を出力
5:Carクラスのインスタンスcarを作成
  □ car.descriptionメソッドを呼び出し、戻り値を出力
  □ car.typeメソッドを呼び出し、戻り値を出力

6:Bikeクラスのインスタンスbikeを作成
  □ bike.descriptionメソッドを呼び出し、戻り値を出力
  □ bike.typeメソッドを呼び出し、戻り値を出力

Q
ヒント2【穴埋め問題にする】

以下のコードをコピーし、コメントに従ってコードを完成させて下さい。

# 親クラス「Vehicle」を定義
class Vehicle
  # 乗り物の詳細を出力するメソッド
  def description
    "これは乗り物です。"
  end

  # 乗り物の種類を出力するメソッド
  def type
    "この乗り物は一般的なものです。"
  end
end

# 子クラス「Car」を定義
class Car < Vehicle
=begin
【穴埋め問題1】
ここに親クラスのdescriptionメソッドをオーバーライドし、superを使って親クラスのメッセージに「 車の種類です。」を追加するコードを書いてください。
=end
end

# 子クラス「Bike」を定義
class Bike < Vehicle
=begin
【穴埋め問題2】
ここに親クラスのdescriptionメソッドをオーバーライドし、完全に新しいメッセージ「これはバイクです。」を出力するコードを書いてください。
=end
end

# オブジェクトを生成し、メソッドを呼び出す
vehicle = Vehicle.new
puts vehicle.description # => これは乗り物です。
puts vehicle.type        # => この乗り物は一般的なものです。

car = Car.new
puts car.description      # => これは乗り物です。 車の種類です。
puts car.type             # => この乗り物は一般的なものです。

bike = Bike.new
puts bike.description     # => これはバイクです。
puts bike.type            # => この乗り物は一般的なものです。

このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。

この問題の解答例と解説

この問題の正解コードとその解説は以下の通りです。

クリックして開いて確認してください。

Q
正解コード
# 親クラス「Vehicle」を定義
class Vehicle
  # 乗り物の詳細を出力するメソッド
  def description
    "これは乗り物です。"
  end

  # 乗り物の種類を出力するメソッド
  def type
    "この乗り物は一般的なものです。"
  end
end

# 子クラス「Car」を定義
class Car < Vehicle
  # descriptionメソッドをオーバーライド
  def description
    super + " 車の種類です。"
  end
end

# 子クラス「Bike」を定義
class Bike < Vehicle
  # descriptionメソッドをオーバーライド
  def description
    "これはバイクです。"
  end
end

# オブジェクトを生成し、メソッドを呼び出す
vehicle = Vehicle.new
puts vehicle.description # => これは乗り物です。
puts vehicle.type        # => この乗り物は一般的なものです。

car = Car.new
puts car.description      # => これは乗り物です。 車の種類です。
puts car.type             # => この乗り物は一般的なものです。

bike = Bike.new
puts bike.description     # => これはバイクです。
puts bike.type            # => この乗り物は一般的なものです。
Q
正解コードの解説

コードをブロックごとに分割して解説します。

クラスの定義と親クラスのメソッド

class Vehicle
  def description
    "これは乗り物です。"
  end

  def type
    "この乗り物は一般的なものです。"
  end
end
  • class Vehicle: 乗り物を表す親クラスを定義しています。このクラスには以下の2つのメソッドがあります。
  • type: 「一般的な乗り物」を示すメッセージを出力するメソッド。このメソッドは子クラスでオーバーライドされません。
  • description: 乗り物の基本情報を出力するメソッド。

子クラスCarでのオーバーライド

class Car < Vehicle
  def description
    super + " 車の種類です。"
  end
end
  • class Car < VehicleVehicleクラスを継承したCarクラスを定義しています。これにより、Vehicleクラスのメソッドをそのまま使ったり、オーバーライドしたりできます。
  • descriptionメソッドのオーバーライド:
  • super: 親クラスのdescriptionメソッドを呼び出しています。superを使うことで親クラスのメッセージ「これは乗り物です。」を取得し、それに「 車の種類です。」を追加しています。

子クラスBikeでのオーバーライド

class Bike < Vehicle
  def description
    "これはバイクです。"
  end
end
  • class Bike < VehicleVehicleクラスを継承したBikeクラスを定義しています。
  • descriptionメソッドの完全なオーバーライド:
  • 親クラスのdescriptionメソッドを使わず、新しいメッセージ「これはバイクです。」を出力するように再定義しています。

インスタンスの作成とメソッドの呼び出し

vehicle = Vehicle.new
puts vehicle.description # => これは乗り物です。
puts vehicle.type        # => この乗り物は一般的なものです。

car = Car.new
puts car.description      # => これは乗り物です。 車の種類です。
puts car.type             # => この乗り物は一般的なものです。

bike = Bike.new
puts bike.description     # => これはバイクです。
puts bike.type            # => この乗り物は一般的なものです。
  • Vehicle.new: 親クラスのインスタンスを作成し、descriptiontypeメソッドを呼び出します。
  • Car.newBike.new: 子クラスのインスタンスを作成し、それぞれのクラスで再定義されたdescriptionメソッドを呼び出します。
  • ポイント: 親クラスから継承したtypeメソッドはオーバーライドされていないため、CarBikeでもそのまま利用できます。

まとめ

このコードではRubyのオブジェクト指向プログラミングにおけるオーバーライドの使い方を学びました。

  • オーバーライドとは: 親クラスで定義されたメソッドを子クラスで再定義し、異なる動作をさせること。
  • superの活用: 親クラスのメソッドを一部利用しながら、独自の動作を追加することが可能。
  • 親クラスの継承: 必要なメソッドを継承することで、コードの重複を防ぎ、柔軟性が向上します。

Rubyのクラスや継承について理解を深める第一歩として、このコードを活用してください!

もっと分かりやすいサイトにするために

この記事を読んで「ここが分かりにくかった」「ここが難しかった」等の意見を募集しています。

世界一わかりやすいRuby学習サイトにするため、ぜひ 問い合わせフォーム からご意見下さい。

<<前のページ

Rubyの記事一覧

次のページ>>

FAQ|Rubyのオーバーライドの使い方と注意点

Q
Q1. Rubyでオーバーライドしたメソッド内で親クラスの処理も実行したいときはどうすればいいですか?

superキーワードを使うことで、オーバーライドしたメソッド内で親クラスの同名メソッドを呼び出すことができます。superを呼び出す位置によって、親クラスの処理を前後に組み込むことも可能です。

Q
Q2. Rubyでオーバーライドとメソッドの再定義にはどんな違いがありますか?

オーバーライドは親クラスから継承したメソッドを子クラスで再定義することを指し、メソッドの再定義は同じクラス内でメソッドを上書きすることを指します。文法的には同じですが、対象となる階層が異なります。

Q
Q3. オーバーライドしたメソッドで引数の数や型を変えても問題ありませんか?

Rubyではメソッドの引数に柔軟性がありますが、引数の数を変更すると親クラスとの互換性が失われる恐れがあります。superを使う場合は特に、引数の扱いに注意が必要です。

記事URLをコピーしました