【Ruby】レッスン5-07:クラスの継承を使って親クラスの機能を再利用しよう

一つ前のページでは正規表現について学習しました。
今回は クラスの継承 について見ていきましょう。
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の継承機能でコードの再利用を実現しよう

クラスの継承とは他のクラスの機能を引き継ぎ再利用できる仕組みです。
これはオブジェクト指向プログラミング(OOP)の中核となる概念の一つです。

親クラスと子クラスの関係を定義する仕組みとは
継承は基本となる「親クラス」から機能を受け継ぐ「子クラス」を定義する方法です。
この仕組みを使うことで、共通の処理を親クラスにまとめ、コードの再利用性を向上させることができます。
例えば多くのクラスで似たような振る舞いを実装する際、親クラスにその振る舞いをまとめることで、重複を防ぐことが可能です。
また子クラスは親クラスのメソッドや属性をそのまま使えるほか、独自の機能を追加することもできます。
継承を使うためのRubyの構文ルール
Rubyではクラスを継承する際に親クラス名を <
を使って指定します。
構文は次のとおりです。
class 子クラス名 < 親クラス名 # 子クラスの独自のメソッドやプロパティ end
例えば以下のようなコードが考えられます。
class Animal # 親クラスの定義 def speak puts "動物の鳴き声" end end class Dog < Animal # Animalクラスを継承するDogクラス(子クラス)の定義 end
この例ではDog
クラスは Animal
クラスを継承しています。
Dog
クラスは特別なコードを追加していなくても、Animal
クラスで定義されたメソッドを使用することができます。
親クラスからメソッドを受け継ぐ実装例
継承を利用する実例を見てみましょう。
class Animal # 親クラスの定義 def initialize(name) @name = name end def speak puts "#{@name}は音を出します。" end end class Dog < Animal # Animalクラスを継承したDogクラスの定義 end class Cat < Animal # Animalクラスを継承したCatクラスの定義 end dog = Dog.new("ポチ") # インスタンス生成 cat = Cat.new("タマ") # インスタンス生成 dog.speak # Dogクラスは親クラスのspeakメソッドを使用できる。 cat.speak # 同上。出力:タマは音を出します。
この例ではDog
クラスと Cat
クラスは、それぞれ親クラスである Animal
クラスを継承しています。
initialize
メソッドや speak
メソッドを子クラスで特別に書かなくても、親クラスで定義されたものをそのまま使用できます。
コードの効率化や保守性が向上する継承の利点
- コードの再利用性:
共通のコードを親クラスにまとめることで、子クラス間で重複を避けられます。 - 保守性の向上:
親クラスを変更すればその変更が全ての子クラスに反映されるため、メンテナンスが容易になります。 - 柔軟性の向上:
子クラスで独自の振る舞いを追加することで、柔軟に機能を拡張できます。
ただし継承を多用しすぎると設計が複雑になり、意図しない動作の原因となる場合があります。
適切な設計を心がけましょう。
まとめ
Rubyのクラスの継承はコードを効率化し、保守性を高める強力な手法です。
親クラスを通じて共通の機能を管理し、子クラスで必要な場面に応じた機能を持たせることで、柔軟かつ整理されたコードを書くことができます。
適切な場面で活用することで、学習が進んだ際により高度な設計をスムーズに理解する助けになります。
練習問題|クラスの継承を使って動物クラスを拡張しよう

クラスの継承をしっかりと身に着けるため、練習問題に挑戦しましょう。
動物と犬クラスで継承の仕組みを実装しよう
Rubyの「クラスの継承」の仕組みを使って、動物と犬をモデルにしたプログラムを作成してみましょう。
このプログラムでは動物クラスを親クラスとし、その機能を犬クラスで拡張します。
動物クラスには挨拶を行う機能を持たせ、犬クラスには特有の「吠える」機能を追加します。
それぞれのクラスを使ったインスタンスを作成し、適切なメソッドを呼び出して動作を確認してください。
以下の要件に従ってコードを完成させてください。
- 動物クラスを作成し、以下を実装すること。
initialize
メソッドで名前を受け取り、それをインスタンス変数@name
に格納すること。greet
メソッドを作成し「こんにちは!私は○○です。」という形式で名前を表示すること。
- 犬クラスを作成し、動物クラスを継承すること。
bark
メソッドを作成し「○○はワンワンと吠えます。」という形式で出力すること。
- 動物クラスのインスタンスを作成し
greet
メソッドを呼び出すこと。 - 犬クラスのインスタンスを作成し以下を実行すること。
- 継承した
greet
メソッドを呼び出すこと。 - 独自に定義した
bark
メソッドを呼び出すこと。
- 継承した
ただし、以下のような実行結果となること。
こんにちは!私は一般的な動物です。 こんにちは!私はポチです。 ポチはワンワンと吠えます。
【ヒント】自力で解くのが難しい人へ
1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。
- ヒント1【コードの構成を見る】
-
正解のコードは上から順に以下のような構成となっています。
1:Animalクラスを定義
□ initializeメソッドを定義し、名前を受け取りインスタンス変数@nameに格納
□ greetメソッドを定義し、インスタンス変数@nameを使用して挨拶文を出力2:Animalクラスを継承してDogクラスを定義
□ barkメソッドを定義し、インスタンス変数@nameを使用して吠えるメッセージを出力3:Animalクラスのインスタンスを作成し、「一般的な動物」を名前に設定
□ animalオブジェクトのgreetメソッドを呼び出し、挨拶文を出力4:Dogクラスのインスタンスを作成し、「ポチ」を名前に設定
□ dogオブジェクトのgreetメソッドを呼び出し、Animalクラスの挨拶文を出力
□ dogオブジェクトのbarkメソッドを呼び出し、Dogクラス特有の吠えるメッセージを出力
- ヒント2【穴埋め問題にする】
-
以下のコードをコピーし、コメントに従ってコードを完成させて下さい。
# 動物クラスを定義します。 class Animal # 初期化メソッドで名前を設定します。 =begin 【穴埋め問題1】 ここにinitializeメソッドを定義し、名前を受け取りインスタンス変数@nameに格納するコードを書いてください。 =end # 動物が挨拶をするメソッド =begin 【穴埋め問題2】 ここにgreetメソッドを定義し、「こんにちは!私は○○です。」という形式で名前を表示するコードを書いてください。 =end end # 動物クラスを継承して犬クラスを作成します。 =begin 【穴埋め問題3】 ここにDogクラスを作成し、Animalクラスを継承するコードを書いてください。 =end # 犬専用のメソッドを定義します。 =begin 【穴埋め問題4】 ここにbarkメソッドを定義し、「○○はワンワンと吠えます。」という形式で出力するコードを書いてください。 =end end # 動物クラスのインスタンスを作成します。 animal = Animal.new("一般的な動物") animal.greet # 動物クラスの挨拶メソッドを呼び出します。 # 犬クラスのインスタンスを作成します。 dog = Dog.new("ポチ") dog.greet # 親クラス(Animal)の挨拶メソッドを使用します。 dog.bark # 子クラス(Dog)の専用メソッドを使用します。
このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。
この問題の解答例と解説
この問題の正解コードとその解説は以下の通りです。
クリックして開いて確認してください。
- 正解コード
-
# クラスの継承について学ぶためのサンプルコード # クラスの基本と継承を使って、動物と犬の例を示します。 # 動物クラスを定義します。 class Animal # 初期化メソッドで名前を設定します。 def initialize(name) @name = name end # 動物が挨拶をするメソッド def greet puts "こんにちは!私は#{@name}です。" end end # 動物クラスを継承して犬クラスを作成します。 class Dog < Animal # 犬専用のメソッドを定義します。 def bark puts "#{@name}はワンワンと吠えます。" end end # 動物クラスのインスタンスを作成します。 animal = Animal.new("一般的な動物") animal.greet # 動物クラスの挨拶メソッドを呼び出します。 # 犬クラスのインスタンスを作成します。 dog = Dog.new("ポチ") dog.greet # 親クラス(Animal)の挨拶メソッドを使用します。 dog.bark # 子クラス(Dog)の専用メソッドを使用します。
- 正解コードの解説
-
コードをブロックごとに分割して解説します。
動物クラスの定義
class Animal def initialize(name) @name = name end def greet puts "こんにちは!私は#{@name}です。" end end
class Animal
Animalという名前のクラスを定義します。クラスはオブジェクトの設計図で、データとその動作をまとめます。def initialize(name)
初期化メソッド(コンストラクタ)です。インスタンスが作成されるときに名前を引数として受け取り、@name
というインスタンス変数に格納します。def greet
greetメソッドではputs
を使ってインスタンスの名前を含む挨拶文を出力します。#{@name}
でインスタンス変数を文字列の中に埋め込みます。
犬クラスの定義
class Dog < Animal def bark puts "#{@name}はワンワンと吠えます。" end end
class Dog < Animal
DogクラスはAnimalクラスを継承しています。<
記号を使うことで、Animalクラスのメソッドやデータをそのまま利用できます。def bark
barkメソッドは犬特有の動作を定義しています。このメソッドではputs
を使い、名前と「吠える」メッセージを出力します。- ポイント:
Animalクラスを継承することで名前の設定や挨拶機能を再実装する必要がなくなり、新しい機能(barkメソッド)を追加するだけで済みます。
動物と犬のインスタンスを作成
animal = Animal.new("一般的な動物") animal.greet dog = Dog.new("ポチ") dog.greet dog.bark
animal = Animal.new("一般的な動物")
Animalクラスのインスタンスを作成します。このインスタンスは「一般的な動物」という名前を持ちます。animal.greet
Animalクラスのgreetメソッドを呼び出して挨拶文を出力します。dog = Dog.new("ポチ")
Dogクラスのインスタンスを作成します。「ポチ」という名前を持つ犬になります。DogクラスはAnimalクラスを継承しているため、initializeメソッドは再利用されています。dog.greet
Dogクラスのインスタンスでありながら、親クラスであるAnimalのgreetメソッドを呼び出します。dog.bark
Dogクラス独自のbarkメソッドを呼び出して、吠えるメッセージを出力します。
まとめ
このコードでは、Rubyの「クラス」と「継承」を学びました。
継承を利用することで共通する機能を親クラスにまとめ、子クラスで独自の機能を追加できます。これによりコードの再利用性と可読性が向上します。
この仕組みを理解することで、現実世界のオブジェクトをプログラムで表現しやすくなります。
ぜひ自分で別の動物クラスや機能を追加してみて、継承の利便性を体験してください!
FAQ|Rubyのクラス継承の理解を深めよう
- Q1. Rubyで親クラスのメソッドを子クラスで上書き(オーバーライド)するにはどうすればいいですか?
-
子クラス内で親クラスと同じ名前のメソッドを定義するだけでオーバーライドが可能です。元の親メソッドを呼び出したい場合は
super
を使うと便利です。
- Q2. Rubyの継承では、initializeメソッドも引き継がれますか?
-
はい、initializeメソッドも親クラスから子クラスに継承されます。ただし、子クラスでinitializeを定義し直すと親のinitializeは無効になるため、必要に応じて
super
を使って親の処理を呼び出すことが重要です。
- Q3. 複数の子クラスに共通する処理は、継承以外にもまとめられますか?
-
共通処理をまとめるには、モジュールを使った「ミックスイン」が効果的です。ただし、ミックスインはLesson5-11で詳しく扱うため、ここでは継承を通じたコード再利用の基本に集中しましょう。