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
これにより、ChildClass
はParentClass
の機能を全て持つようになり、必要に応じて新しいメソッドを追加したり、既存のメソッドを上書き(オーバーライド)することが可能です。
実例:動物クラスと犬クラス
例えば、動物のクラスを作り、それを元に犬のクラスを作成する場合を考えましょう。
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
を使うことで親クラスの機能を拡張しつつ、新しい振る舞いを追加することが可能です。
継承のポイント
- コードの再利用: 親クラスに共通の機能を定義し、子クラスでは必要な部分だけをカスタマイズできます。
- オーバーライド: 子クラスで親クラスのメソッドを上書きすることができます。上書きした場合、親クラスの同名メソッドは呼ばれなくなりますが、
super
を使って呼び出すことも可能です。 - オブジェクト指向の基本概念: 継承は、オブジェクト指向プログラミングの中心的な考え方です。実世界のオブジェクトをモデル化する際に便利です。
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.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
クラスのメソッドを利用して、追加した乗り物の情報を表示
以下のコードをコピーし、コメントに従ってコードを完成させて下さい。
# 乗り物を表す基本クラス 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を活用しています。
問題ないことは確認していますが、もし間違いや表現の違和感などありましたら、ご指摘頂けると大変助かります。