🌿
Rubyのクラス基礎
Rubyのクラスについてです
クラスの作成
class User
def initialize(name, score) # インスタンス作成時に実行される、インスタンス変数という
@name = name # @が1つのものはインスタンス変数
@score = score
end
end
これでクラスの作成ができました、クラス名は大文字スタートです。
メソッドの定義
class User
def initialize(name, score) # インスタンス作成時に実行される、インスタンス変数という
@name = name
@score = score
end
def get_info
"Name: #{@name}, Score: #{@score}"
end
end
インスタンスの作成
user1 = User.new("taro", 70)
user2 = User.new("hiro", 90)
インスタンスからメソッドを実行する
puts user1.get_info # 出力されます
ちなみにメソッドの中にputsを入れない理由ですが、汎用性を高めるためだったと思います
メソッドにputsを入れると出力する時にしか使えなくなってしまいますね
インスタンスの値の取得や書き換え
以下のようなメソッドを定義することにより書き換えなどが可能です
インスタンスの値を取得するメソッド
getterといいます
def name
@name
end
puts user1.name # taro
インスタンス変数の値を書き換えるメソッド
setterという
def name=(new_name)
@name = new_name
end
user1.name = "big g"
puts user1.name # big g
メソッド名あたりが特殊な書き方になっていますが、インスタンス変数の値を変更するメソッドは
メソッド名と引数の間に「=」を入れます。また、「=」の両端にスペースは入れてはいけません
setterとgetterを簡略化
setterとgetterはよく使われるので簡略化することが可能です
クラスの先頭にattr_accessor
を付与することでメソッドを定義しなくとも取得や書き換えが可能です
class User
attr_accessor :name
def initialize(name, score) # インスタンス作成時に実行される、インスタンス変数という
@name = name
@score = score
end
end
user1 = User.new("taro", 70)
user2 = User.new("hiro", 90)
puts user1.name # taro
user1.name = "nichika"
puts user1.name # nichika
使い分け
attr_witter
とするとsetterのみ
attr_reader
とするとgetterのみ可能にできます
クラス全体の変数
どれだけインスタンスを生成したか保持したい時などはクラス全体用の変数を作ります
class User
@@count = 0
def initialize(name, score) # インスタンス作成時に実行される、インスタンス変数という
@name = name
@score = score
@@count += 1
end
end
クラスの変数を出力する
def self.get_info
"Count: #{@@count}"
end
puts User.get_info # クラスメソッドという、クラス名.メソッド名
メソッドの中でメソッドを呼び出す
まずスコアを判定するメソッドを追加します
def get_info
"Name: #{@name}, Score: #{@score} -> #{get_result}" # get_resultメソッドの呼び出し
end
def get_result
@score >= 80 ? "Pass" : "Fail"
end
privateな関数
private # ここより下に記述したメソッドはクラス外から呼び出せない
別のクラスのインスタンスをインスタンス変数に渡しメソッドを実行する
class Score
def initialize(subject, score)
@subject = subject
@score = score
end
def get_info
"#{@subject}/#{@score} -> #{get_result}"
end
private
def get_result
@score >= 80 ? "Pass" : "Fail"
end
end
class User
def initialize(name, score)
@name = name # @が1つのものはインスタンス変数
@score = score
end
def get_info
"Name: #{@name}, Score: #{@score.get_info}"
end
end
user1 = User.new("Taro", Score.new("Math", 70)) # @scoreにScoreクラスのインスタンスを渡してる
user2 = User.new("Jiro", Score.new("English", 90))
puts user1.get_info # Name: Taro, Score: Math/70
継承
こちらもクラスの継承が可能です
class Score
def initialize(subject, score)
@subject = subject
@score = score
end
def get_info
"#{@subject}/#{@score} -> #{get_result}"
end
private
def get_result
@score >= 80 ? "Pass" : "Fail"
end
end
# 子クラス
class MathScore < Score # Scoreクラスを継承
def initialize(score)
@score = score
super("Math", score) # 親クラスのinitializeを実行している
end
private
def get_result # 親クラスのメソッドを上書き、overrideという
@score >= 50 ? "Pass" : "Fail"
end
end
class EnglishScore < Score
def initialize(score)
@score = score
super("English", score) # 親クラスのinitializeを実行している
end
end
class User
def initialize(name, score)
@name = name # @が1つのものはインスタンス変数
@score = score
end
def get_info
"Name: #{@name}, Score: #{@score.get_info}"
end
end
user1 = User.new("Taro", MathScore.new(70)) # @scoreにScoreクラスのインスタンスを渡してる
user2 = User.new("Jiro", EnglishScore.new(90))
puts user1.get_info # Name: Taro, Score: Math/70 -> Pass
puts user2.get_info # Name: Jiro, Score: English/90 -> Pass
モジュールを使用してみよう
userとscoreで同じメソッドを使用するならモジュールから引っ張ってくればいいじゃん
そっちの方が楽だし
module Loggable
def show_log
puts "Instance created: #{self.class}"
end
end
class Score
include Loggable # インスタンスメソッドとして使用可能
# extend Loggable クラスメソッドとして使用可能
def initialize(subject, score)
@subject = subject
@score = score
show_log # インスタンス生成時にメソッドを実行する
end
def get_info
"#{@subject}/#{@score} -> #{get_result}"
end
private
def get_result
@score >= 80 ? "Pass" : "Fail"
end
end
# 子クラス
class MathScore < Score
def initialize(score)
@score = score
super("Math", score)
end
private
def get_result
@score >= 50 ? "Pass" : "Fail"
end
end
class EnglishScore < Score
def initialize(score)
@score = score
super("English", score)
end
end
class User
include Loggable
def initialize(name, score)
@name = name
@score = score
show_log
end
def get_info
"Name: #{@name}, Score: #{@score.get_info}"
end
end
user1 = User.new("Taro", MathScore.new(70))
user2 = User.new("Jiro", EnglishScore.new(90))
# 実行結果
# Instance created: MathScore
# Instance created: User
# Instance created: EnglishScore
# Instance created: User
このようにモジュールを使って、継承関係にないクラスに共通の機能を組み込む仕組みを「ミックスイン」と呼びます。
クラスを介さずモジュールを使用する
為替換算するモジュールを元に考えていきます
module CurrencyHelpers
JPY_TO_USD = 0.0068 # 換算レート定数
USD_TO_JPY = 146.78 # 換算レート定数
def self.jpy_to_usd(jpy) # モジュールの外で呼び出すためにselfを使用する、クラスと概念似てる
jpy * JPY_TO_USD
end
def self.usd_to_jpy(usd)
usd * USD_TO_JPY
end
end
puts CurrencyHelpers.jpy_to_usd(100000) # 680.0
puts CurrencyHelpers.usd_to_jpy(1000) # 146780.0
puts CurrencyHelpers::JPY_TO_USD # 0.0068
puts CurrencyHelpers::USD_TO_JPY # 146.78
Discussion