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

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の継承機能でコードの再利用を実現しよう

クラスの継承とは他のクラスの機能を引き継ぎ再利用できる仕組みです。

これはオブジェクト指向プログラミング(OOP)の中核となる概念の一つです。

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

親クラスと子クラスの関係を定義する仕組みとは

継承は基本となる「親クラス」から機能を受け継ぐ「子クラス」を定義する方法です。

この仕組みを使うことで、共通の処理を親クラスにまとめ、コードの再利用性を向上させることができます。

例えば多くのクラスで似たような振る舞いを実装する際、親クラスにその振る舞いをまとめることで、重複を防ぐことが可能です。

また子クラスは親クラスのメソッドや属性をそのまま使えるほか、独自の機能を追加することもできます。

継承を使うための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 メソッドを子クラスで特別に書かなくても、親クラスで定義されたものをそのまま使用できます。

コードの効率化や保守性が向上する継承の利点

  1. コードの再利用性:
    共通のコードを親クラスにまとめることで、子クラス間で重複を避けられます。
  2. 保守性の向上:
    親クラスを変更すればその変更が全ての子クラスに反映されるため、メンテナンスが容易になります。
  3. 柔軟性の向上:
    子クラスで独自の振る舞いを追加することで、柔軟に機能を拡張できます。

ただし継承を多用しすぎると設計が複雑になり、意図しない動作の原因となる場合があります。

適切な設計を心がけましょう。

まとめ

Rubyのクラスの継承はコードを効率化し、保守性を高める強力な手法です。

親クラスを通じて共通の機能を管理し、子クラスで必要な場面に応じた機能を持たせることで、柔軟かつ整理されたコードを書くことができます。

適切な場面で活用することで、学習が進んだ際により高度な設計をスムーズに理解する助けになります。

練習問題|クラスの継承を使って動物クラスを拡張しよう

クラスの継承をしっかりと身に着けるため、練習問題に挑戦しましょう。

動物と犬クラスで継承の仕組みを実装しよう

Rubyの「クラスの継承」の仕組みを使って、動物と犬をモデルにしたプログラムを作成してみましょう。

このプログラムでは動物クラスを親クラスとし、その機能を犬クラスで拡張します。

動物クラスには挨拶を行う機能を持たせ、犬クラスには特有の「吠える」機能を追加します。

それぞれのクラスを使ったインスタンスを作成し、適切なメソッドを呼び出して動作を確認してください。

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

  1. 動物クラスを作成し、以下を実装すること。
    • initializeメソッドで名前を受け取り、それをインスタンス変数@nameに格納すること。
    • greetメソッドを作成し「こんにちは!私は○○です。」という形式で名前を表示すること。
  2. 犬クラスを作成し、動物クラスを継承すること。
    • barkメソッドを作成し「○○はワンワンと吠えます。」という形式で出力すること。
  3. 動物クラスのインスタンスを作成しgreetメソッドを呼び出すこと。
  4. 犬クラスのインスタンスを作成し以下を実行すること。
    • 継承したgreetメソッドを呼び出すこと。
    • 独自に定義したbarkメソッドを呼び出すこと。

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

こんにちは!私は一般的な動物です。
こんにちは!私はポチです。
ポチはワンワンと吠えます。

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

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

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

正解のコードは上から順に以下のような構成となっています。

1:Animalクラスを定義
  □ initializeメソッドを定義し、名前を受け取りインスタンス変数@nameに格納
  □ greetメソッドを定義し、インスタンス変数@nameを使用して挨拶文を出力

2:Animalクラスを継承してDogクラスを定義
  □ barkメソッドを定義し、インスタンス変数@nameを使用して吠えるメッセージを出力

3:Animalクラスのインスタンスを作成し、「一般的な動物」を名前に設定
  □ animalオブジェクトのgreetメソッドを呼び出し、挨拶文を出力

4:Dogクラスのインスタンスを作成し、「ポチ」を名前に設定
  □ dogオブジェクトのgreetメソッドを呼び出し、Animalクラスの挨拶文を出力
  □ dogオブジェクトのbarkメソッドを呼び出し、Dogクラス特有の吠えるメッセージを出力

Q
ヒント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)の専用メソッドを使用します。

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

この問題の解答例と解説

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

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

Q
正解コード
# クラスの継承について学ぶためのサンプルコード
# クラスの基本と継承を使って、動物と犬の例を示します。

# 動物クラスを定義します。
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)の専用メソッドを使用します。
Q
正解コードの解説

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

動物クラスの定義

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の「クラス」と「継承」を学びました。

継承を利用することで共通する機能を親クラスにまとめ、子クラスで独自の機能を追加できます。これによりコードの再利用性と可読性が向上します。

この仕組みを理解することで、現実世界のオブジェクトをプログラムで表現しやすくなります。

ぜひ自分で別の動物クラスや機能を追加してみて、継承の利便性を体験してください!

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

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

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

<<前のページ

Rubyの記事一覧

次のページ>>

FAQ|Rubyのクラス継承の理解を深めよう

Q
Q1. Rubyで親クラスのメソッドを子クラスで上書き(オーバーライド)するにはどうすればいいですか?

子クラス内で親クラスと同じ名前のメソッドを定義するだけでオーバーライドが可能です。元の親メソッドを呼び出したい場合は super を使うと便利です。

Q
Q2. Rubyの継承では、initializeメソッドも引き継がれますか?

はい、initializeメソッドも親クラスから子クラスに継承されます。ただし、子クラスでinitializeを定義し直すと親のinitializeは無効になるため、必要に応じて super を使って親の処理を呼び出すことが重要です。

Q
Q3. 複数の子クラスに共通する処理は、継承以外にもまとめられますか?

共通処理をまとめるには、モジュールを使った「ミックスイン」が効果的です。ただし、ミックスインはLesson5-11で詳しく扱うため、ここでは継承を通じたコード再利用の基本に集中しましょう。

記事URLをコピーしました