Rubyにおけるクラスの継承とオーバーライド
クラスの継承
ざっくり基本設計
目的:メンテナンス性を高める、使い勝手をよくする
手段:
1)基本的な機能を親クラスにて定義
2)独自のメソッドを子クラスにて定義
3)子クラスは親クラスを継承
具体例:
目的:飲食店のメニューを表示したい。
名前、値段、カロリー(※食べ物についてのみ)、容量(※飲み物についてのみ)
親クラス・・・食べ物/飲み物のメニューを表示するインスタンスメソッドを持つ。
名前:ハンバーガー 値段:¥800
名前:コーヒー 値段:\200
子クラス1・・・食べ物のカロリーを表示するインスタンスメソッドを持つ
カロリー:600kcal
子クラス2・・・飲み物の容量を表示するインスタンスメソッドを持つ
容量:300ml
・継承した子クラスには、親クラスのインスタンスメソッドとインスタンス変数が引き継がれる
実装(クラスの継承)
親クラス
class Menuattr_accessor :nameattr_accessor :price/*インスタンスを使用時、受け取った引数の値をインスタンス変数に代入して、class内で使えるようにする :/def initialize(name:, price:)self.name = nameself.price = priceend/*infoメソッドの定義。受け取った引数の値を、名前・円の文字列にくっつけて返す */def inforeturn”#{self.name}#{self.price}円”endend
子クラス①
//親クラスMenuの継承require “./menu”class Food < Menu
end
子クラス②
//親クラスMenuの継承require “./menu”class Drink < Menu
end
require “./food”require “./drink”/* Foodクラスのインスタンスを生成。Foodクラスは親であるMenuクラスを継承しているので、Menuクラスで定義されたインスタンス変数name,priceも使用できる*/food1 = Food.new(name:”ハンバーガー”, price:600)/* Menuクラスで定義されたインスタンスメソッドinfoを使用*/puts food1.info //結果)ハンバーガー 600円/* 同上 */drink1 = Drink.new(name:”コーヒー”,price:200)puts drink1.info //結果)コーヒー 200円
実装(子クラス独自のインスタンス変数・インスタンスメソッド)
子クラス①
//親クラスMenuの継承require “./menu”class Food < Menu//子クラス独自のインスタンス変数attr_accessor :calorie//子クラス独自のインスタンスメソッドdef calorie_inforeturn”#{self.name}は#{self.calorie}kcalです”endend
//親クラスMenuの継承require “./menu”class Drink < Menu//子クラス独自のインスタンス変数attr_accessor :amount//子クラス独自のインスタンスメソッドdef amount_inforeturn “#{self.name}は#{self.amount}mLです”endend
require “./food”
require “./drink”food1 = Food.new(name: “ピザ”, price: 800)
food1.calorie = 700//food1に対してcalorie_infoメソッドを呼び出して戻り値を出力
puts food1.calorie_info //結果)ピザは700kcalですdrink1 = Drink.new(name:”コーヒー”, price: 300)
drink1.amount = 300//drink1に対してamount_infoメソッドを呼び出して戻り値を出力
puts drink1.amount_info //結果)コーヒーは300mLです
オーバーライド
目的:親クラスのメソッドを上書き
手段:親クラスにあるメソッドと同じ名前のメソッドを、子クラスで定義する
具体例:
目的:飲食店のメニューを表示したい。
名前、値段、カロリー(※食べ物についてのみ)、容量(※飲み物についてのみ)
親クラス・・・食べ物/飲み物のメニューを表示するインスタンスメソッドを持つ。
名前:ハンバーガー 値段:¥800
名前:コーヒー 値段:\200
子クラス1・・・食べ物の名前、値段、カロリーを表示するインスタンスメソッドを定義して、親クラスの、メニューを表示するインスタンスメソッドをオーバーライドする
ハンバーガー、¥800、600kcal
子クラス2・・・飲み物の名前、値段、容量を表示するインスタンスメソッドを定義して、親クラスの、メニューを表示するインスタンスメソッドをオーバーライドする
コーヒー、¥300、300ml
実装
class Menuattr_accessor :nameattr_accessor :price/*インスタンスを使用時、受け取った引数の値をインスタンス変数に代入して、class内で使えるようにする :/def initialize(name:, price:)self.name = nameself.price = priceend/*受け取った引数の値を、名前・円の文字列にくっつけて返す。オーバーライドの対象 */def inforeturn”#{self.name}#{self.price}円”endend
//親クラスMenuの継承require “./menu”class Food < Menu//子クラス独自のインスタンス変数attr_accessor :calorie//infoメソッドを定義して、親クラスのinfoメソッドをオーバーライドdef inforeturn”#{self.name}#{self.price}円 (#{self.calorie}kcal)”endend
//親クラスMenuの継承require “./menu”class Drink < Menu//子クラス独自のインスタンス変数attr_accessor :amount//infoメソッドを定義して、親クラスのインスタンスメソッドをオーバーライドdef inforeturn”#{self.name}#{self.price}円 (#{self.amount}mL)”endend
require “./food”require “./drink”/* Foodクラスのインスタンスを生成。Foodクラスは親であるMenuクラスを継承しているので、Menuクラスで定義されたインスタンス変数name,priceも使用できる*/food1 = Food.new(name:”ハンバーガー”, price:600)food1.calorie = 600food2 = Food.new(name:”ポテト”, price:300)food2.calorie = 500drink1 = Drink.new(name: “コーヒー”, price: 300)drink1.amount = 300drink2 = Drink.new(name: “お茶”, price: 200)drink2.amount = 400menus = [food1, food2, drink1, drink2]/* メニューを一覧表示*/index = 0menus.each do |menu|puts “#{index}. #{menu.info}” //ここでFoodクラスのinfoとDrinkクラスのinfoがそれぞれ使われるindex += 1end出力結果)0.ハンバーガー 600円(600kcal)1.ポテト 300円(500kcal)2.コーヒー 300円(300mL)3.お茶 200円(400mL)