Ruby練習問題3-4:クラスの継承を理解しよう

記事内に商品プロモーションを含む場合があります

Rubyの初心者向け問題3-4:クラスの継承を理解しよう

この問題を解くために必要な知識:
【レベル1~2の知識】
コメントの書き方、変数と定数、基本データ型、四則演算と演算子、入力と出力、文字列操作、分岐処理(if、if~else、elsif、case)、繰り返し処理(for、while、until、each)、範囲(Range)、例外処理(begin-rescue-end)、配列(Array)、ハッシュ(Hash)、コレクション操作(配列、ハッシュの操作)、Enumerableモジュール

【レベル3の知識】
メソッドの定義と呼び出し、メソッドの戻り値、クラスの定義と使用、コンストラクタ、クラスの継承、モジュールの定義と使用ミックスイン

<<前の問題 問題集Top 次の問題>>

Rubyの文法「クラスの継承」とは

ここではクラスの継承の意味や使い方を復習します。必要ない方はここをクリックして練習問題へ飛びましょう。



Rubyのプログラミングにおいて、クラスの継承は非常に重要な概念です。

継承を使うことで、あるクラスの機能を別のクラスで再利用し、拡張することができます。

これにより、コードの再利用性が高まり、オブジェクト指向の設計がより簡潔に行えます。

クラス継承の基本

クラスの継承は、既存のクラスを基にして新しいクラスを作るための機能です。

Rubyでは、<を使って継承を行います。基本の構文は以下のようになります。

class ParentClass
  # 親クラスのメソッドや属性
end

class ChildClass < ParentClass
  # 子クラスは親クラスのメソッドを継承しつつ、自分独自のメソッドも持つことができる
end

これにより、ChildClassParentClassの機能を全て持つようになり、必要に応じて新しいメソッドを追加したり、既存のメソッドを上書き(オーバーライド)することが可能です。

実例:動物クラスと犬クラス

例えば、動物のクラスを作り、それを元に犬のクラスを作成する場合を考えましょう。

class Animal
  def speak
    "Hello!"
  end
end

class Dog < Animal
  def speak
    "Woof!"
  end
end

dog = Dog.new
puts dog.speak  # => "Woof!"

この例では、Animalクラスが基本的な動物の動作(speakメソッド)を持ちます。

DogクラスはAnimalクラスを継承しており、speakメソッドを上書きしています。

Dogのインスタンスは、新しく定義された"Woof!"という出力を行います。

親クラスのメソッドを呼び出す

もし、子クラスで親クラスのメソッドをそのまま使いたい場合は、superを使うことで親クラスのメソッドを呼び出すことができます。

class Animal
  def speak
    "Hello!"
  end
end

class Dog < Animal
  def speak
    super + " Woof!"
  end
end

dog = Dog.new
puts dog.speak  # => "Hello! Woof!"

このように、superを使うことで親クラスの機能を拡張しつつ、新しい振る舞いを追加することが可能です。

継承のポイント

  1. コードの再利用: 親クラスに共通の機能を定義し、子クラスでは必要な部分だけをカスタマイズできます。
  2. オーバーライド: 子クラスで親クラスのメソッドを上書きすることができます。上書きした場合、親クラスの同名メソッドは呼ばれなくなりますが、superを使って呼び出すことも可能です。
  3. オブジェクト指向の基本概念: 継承は、オブジェクト指向プログラミングの中心的な考え方です。実世界のオブジェクトをモデル化する際に便利です。




Ruby練習問題3-4_乗り物管理プログラムを作ろう

クラス継承を使って、乗り物を表すクラスとその派生クラス(車やバイク)を作成し、それらを管理するガレージのプログラムを作成しましょう。

ガレージには複数の乗り物を追加でき、すべての乗り物の情報を表示することができます。

この問題の要件

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

  • Vehicleという基本クラスを作成し、initializeメソッドで乗り物の名前、種類、最高速度を設定すること。
  • Vehicleクラスに、乗り物の情報を表示するdisplay_infoメソッドを定義すること。
  • CarクラスとMotorcycleクラスをVehicleクラスから継承し、それぞれdisplay_infoメソッドを上書きして「これは車です」「これはバイクです」と表示すること。
  • Garageクラスを作成し、乗り物を格納するための配列を用意し、add_vehicleメソッドで乗り物を追加できるようにすること。
  • Garageクラスに、すべての乗り物の情報を表示するdisplay_vehiclesメソッドを定義すること。
  • ユーザーはプログラムを通じて車やバイクを追加し、ガレージ内のすべての乗り物の情報を表示できること。

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

----- ↓出力される結果の例↓ -----

1. 車を追加
2. バイクを追加
3. 全ての乗り物の情報を表示
4. 終了
1
車の名前を入力してください:
フェラーリ
最高速度を入力してください:
320
車を追加しました。
1. 車を追加
2. バイクを追加
3. 全ての乗り物の情報を表示
4. 終了
2
バイクの名前を入力してください:
ヤマハ
最高速度を入力してください:
150
バイクを追加しました。
1. 車を追加
2. バイクを追加
3. 全ての乗り物の情報を表示
4. 終了
3
全ての乗り物の情報:
名前: フェラーリ, 種類: 車, 最高速度: 320km/h
これは車です。
名前: ヤマハ, 種類: バイク, 最高速度: 150km/h
これはバイクです。
1. 車を追加
2. バイクを追加
3. 全ての乗り物の情報を表示
4. 終了
4
プログラムを終了します。

----- ↑出力される結果の例↑ -----

この問題を解くヒント

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

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

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

1.Vehicleクラスの定義
 1-1. initializeメソッドで、@name@type@max_speedの3つのインスタンス変数を定義
 1-2. display_infoメソッドで、乗り物の名前、種類、最高速度を表示

2.Carクラスの定義(Vehicleクラスを継承)
 2-1. display_infoメソッドを上書きし、superで親クラスのdisplay_infoを呼び出し、その後「これは車です」と表示

3.Motorcycleクラスの定義(Vehicleクラスを継承)
 3-1. display_infoメソッドを上書きし、superで親クラスのdisplay_infoを呼び出し、その後「これはバイクです」と表示

4.Garageクラスの定義
 4-1. initializeメソッドで、乗り物を格納するための@vehicles配列を定義
 4-2. add_vehicleメソッドで、@vehicles配列に乗り物を追加
 4-3. display_vehiclesメソッドで、@vehicles配列内の全ての乗り物に対してdisplay_infoメソッドを呼び出す

5.メインプログラム
 5-1. Garageクラスのインスタンスを作成
 5-2. ユーザー入力に基づいて、車またはバイクを追加する
 5-3. すべての乗り物の情報を表示するためのメニューを表示
 5-4. ループでユーザーの選択肢に応じた操作を実行(車やバイクの追加、情報の表示、プログラム終了)

6.ユーザーからの入力処理
 6-1. 車またはバイクの名前をユーザーから入力
 6-2. 最高速度をユーザーから入力

7.Garageクラスのメソッドを利用して、追加した乗り物の情報を表示

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

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

# 乗り物を表す基本クラス
class Vehicle
  def initialize(name, type, max_speed)
    @name = name
    @type = type
    @max_speed = max_speed
  end

  # 乗り物の情報を表示するメソッド
  def display_info
=begin 【穴埋め問題1】
ここに、名前、種類、最高速度を表示するコードを書いてください。
=end
  end
end

# 車を表すクラス(Vehicleクラスを継承)
class Car < Vehicle
  def display_info
    super
=begin 【穴埋め問題2】
ここに、"これは車です"と表示するコードを書いてください。
=end
  end
end

# バイクを表すクラス(Vehicleクラスを継承)
class Motorcycle < Vehicle
  def display_info
    super
=begin 【穴埋め問題3】
ここに、"これはバイクです"と表示するコードを書いてください。
=end
  end
end

# ガレージを管理するクラス
class Garage
  def initialize
=begin 【穴埋め問題4】
ここに、乗り物を格納するための配列を初期化するコードを書いてください。
=end
  end

  # 乗り物をガレージに追加するメソッド
  def add_vehicle(vehicle)
=begin 【穴埋め問題5】
ここに、乗り物を配列に追加するコードを書いてください。
=end
  end

  # 全ての乗り物の情報を表示するメソッド
  def display_vehicles
=begin 【穴埋め問題6】
ここに、配列内の全ての乗り物の情報を表示するループを書くコードを書いてください。
=end
  end
end

 

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



解答例と解説

この問題の一つの正解例とそのコードの解説を以下に示します。

正解コードの例

例えば以下のようなプログラムが考えられます。

********************

# 乗り物を表す基本クラス
class Vehicle
  def initialize(name, type, max_speed)
    @name = name
    @type = type
    @max_speed = max_speed
  end

  # 乗り物の情報を表示するメソッド
  def display_info
    puts "名前: #{@name}, 種類: #{@type}, 最高速度: #{@max_speed}km/h"
  end
end

# 車を表すクラス(Vehicleクラスを継承)
class Car < Vehicle
  def display_info
    super
    puts "これは車です。"
  end
end

# バイクを表すクラス(Vehicleクラスを継承)
class Motorcycle < Vehicle
  def display_info
    super
    puts "これはバイクです。"
  end
end

# ガレージを管理するクラス
class Garage
  def initialize
    @vehicles = [] # 乗り物のリストを格納する配列
  end

  # 乗り物をガレージに追加するメソッド
  def add_vehicle(vehicle)
    @vehicles << vehicle
  end

  # 全ての乗り物の情報を表示するメソッド
  def display_vehicles
    @vehicles.each do |vehicle|
      vehicle.display_info
    end
  end
end

# メインプログラム
garage = Garage.new

loop do
  puts "1. 車を追加"
  puts "2. バイクを追加"
  puts "3. 全ての乗り物の情報を表示"
  puts "4. 終了"
  choice = gets.chomp.to_i

  case choice
  when 1
    puts "車の名前を入力してください:"
    name = gets.chomp
    puts "最高速度を入力してください:"
    max_speed = gets.to_i
    car = Car.new(name, "車", max_speed)
    garage.add_vehicle(car)
    puts "車を追加しました。"
  when 2
    puts "バイクの名前を入力してください:"
    name = gets.chomp
    puts "最高速度を入力してください:"
    max_speed = gets.to_i
    motorcycle = Motorcycle.new(name, "バイク", max_speed)
    garage.add_vehicle(motorcycle)
    puts "バイクを追加しました。"
  when 3
    puts "全ての乗り物の情報:"
    garage.display_vehicles
  when 4
    puts "プログラムを終了します。"
    break
  else
    puts "無効な選択です。もう一度入力してください。"
  end
end

********************

コードの解説

このコードは、Rubyの「クラスの継承」を使って、乗り物(車やバイク)を管理するプログラムを作成する例です。

それでは、このコードの各部分について詳しく解説していきます。

Vehicle クラスの定義

class Vehicle
  def initialize(name, type, max_speed)
    @name = name
    @type = type
    @max_speed = max_speed
  end

  def display_info
    puts "名前: #{@name}, 種類: #{@type}, 最高速度: #{@max_speed}km/h"
  end
end

Vehicleクラスは、すべての乗り物の基本となるクラスです。Rubyでは、classキーワードを使ってクラスを定義します。

  • initializeメソッド: このメソッドは、オブジェクトが生成されるときに自動的に呼ばれるコンストラクタです。ここでは、@name@type@max_speedという3つのインスタンス変数が初期化されます。
  • display_infoメソッド: 乗り物の名前、種類、最高速度を表示するメソッドです。このメソッドは、Vehicleクラスを継承したクラスでも使えます。

クラスの継承 – Car クラス

class Car < Vehicle
  def display_info
    super
    puts "これは車です。"
  end
end

Carクラスは、Vehicleクラスを継承しています。<の記号を使って「CarはVehicleの一種である」ことを示しています。

  • superキーワード: superは、親クラス(Vehicleクラス)のメソッドを呼び出すためのものです。ここでは、Vehicleクラスのdisplay_infoメソッドを使って、まず基本情報を表示しています。その後に、”これは車です。”と追加の情報を出力しています。

クラスの継承 – Motorcycle クラス

class Motorcycle < Vehicle
  def display_info
    super
    puts "これはバイクです。"
  end
end

Motorcycleクラスも、Vehicleクラスを継承しています。

Carクラスと同じように、superで親クラスのメソッドを呼び出し、さらに「これはバイクです。」と追加で出力しています。

Garage クラス

class Garage
  def initialize
    @vehicles = []
  end

  def add_vehicle(vehicle)
    @vehicles << vehicle
  end

  def display_vehicles
    @vehicles.each do |vehicle|
      vehicle.display_info
    end
  end
end

Garageクラスは、複数の乗り物を管理するためのクラスです。このクラスでは、次のメソッドを使います。

  • initializeメソッド: 乗り物を格納するための配列@vehiclesを初期化します。
  • add_vehicleメソッド: 新しい乗り物をガレージに追加します。
  • display_vehiclesメソッド: ガレージに格納されたすべての乗り物の情報を表示します。ここでは、eachメソッドを使って、格納されている各乗り物のdisplay_infoメソッドを呼び出しています。

メインプログラム

garage = Garage.new

loop do
  # 乗り物を追加したり、情報を表示する処理
end

メインプログラムでは、Garageクラスのインスタンスを作成し、ユーザーの入力に基づいて車やバイクを追加したり、ガレージ内の乗り物の情報を表示します。

  • Garage.newでガレージオブジェクトを生成します。
  • loopで無限ループを作り、ユーザーが選んだ操作(車やバイクの追加、情報の表示)に応じて処理を実行します。

クラス継承のメリット

このコードで使用されている「クラスの継承」の最大のメリットは、コードの再利用です。

共通の機能(乗り物の情報を表示するdisplay_infoメソッドなど)を親クラス(Vehicleクラス)に定義しておき、子クラス(CarやMotorcycle)では必要な部分だけをカスタマイズすることができます。

これにより、コードの重複を避け、保守性の高いプログラムを作成できます。

<<前の問題 問題集Top 次の問題>>

この問題への質問・コメント

この問題を作成するにあたりAIを活用しています。

問題ないことは確認していますが、もし間違いや表現の違和感などありましたら、ご指摘頂けると大変助かります。






    Ruby練習問題集へ戻る
    トップページへ戻る