【Ruby】Lesson5-08|メソッドのオーバーライドを理解しよう

ながみえ

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

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

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には「オーバーライド」という機能があり、これを使うと親クラスで定義されたメソッドを子クラスから上書きすることができます。

オーバーライドはクラスの柔軟性を高める、非常に重要な技術です。

オーバーライドの概要とコード例

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

オーバーライドを使用することで、同じ名前のメソッドでも子クラスとごに異なる振る舞いを実装できます。

オーバーライドを実装する方法は、単に継承したメソッドと同名のメソッドを定義するだけです。

具体的なコードの例を見てみましょう。

class Animal	# 親クラスの定義
  def speak		# 継承させたいメソッド
    "鳴き声"
  end
end

# 子クラスの定義
class Dog < Animal	# Animalクラスを継承したDogクラスの定義
end
class Cat < Animal	# Animalクラスを継承したCatクラスの定義
  def speak			# speakメソッドをオーバーライド
    "にゃーにゃー"
  end
end

dog = Dog.new	# インスタンス生成
cat = Cat.new	# インスタンス生成
puts dog.speak	# 継承したメソッド。出力:鳴き声
puts cat.speak	# オーバーライドしたメソッド。出力;にゃーにゃー

この例では、Dogクラスが継承したメソッドをそのまま呼び出している一方、Catクラスはオーバーライドして独自のメソッドとして呼び出しています。

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

また、 superキーワード を使うことで親クラスのメソッドを活用しつつ独自メソッドを作ることができます。

class Animal	# 親クラスの定義
  def speak		# 継承させたいメソッド
    "鳴き声"
  end
end

class Fox < Animal	# Animalクラスを継承したFoxクラスの定義
  def speak			# speakメソッドをオーバーライド
    super + "!(元気に鳴いている)"
  end
end

fox = Fox.new	# インスタンス生成
puts fox.speak	# => "鳴き声!(元気に鳴いている)"

このコードを実行すると、以下のように出力されます。

鳴き声!(元気に鳴いている)

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

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

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

まとめ|メソッドを上手に上書きしよう

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

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をコピーしました