5. オブジェクト¶
5.1. オブジェクト指向とは¶
Rubyではすべてのデータはオブジェクトである。例えば整数のクラスは Integer
、文字列のクラスは String
など。
Ruby言語に 最初から組み込まれているクラス と、 組み込みではないが標準的に用意されているクラス がある。
5.2. クラス定義¶
同じクラス名で複数箇所に定義を書いてもよい。その場合は定義が追加されていく。
5.3. メソッド¶
メソッドを実行する時は必ず実行主体となるオブジェクト(「私」が誰かということ)があり、それは self
という変数に入っている。
メソッドを呼び出す時は実行主体となるオブジェクトを指定しないといけないが、指定しない場合は self
が使われる。したがって次の二つは同じ。
foo()
self.foo()
注釈
Rubyに関数や演算子は無く、すべてメソッドである。関数のように使うものは Object
クラスで定義されている(正確には Kernel
モジュールで定義され、 Object
クラスにインポートされている)。 Object
はすべてのクラスのスーパークラスなので、そこで定義されたメソッドはすべてのオブジェクトでメソッド名だけ書いて使うことができる。
5.4. インスタンスの生成¶
クラスAの新しいオブジェクトを作るには、クラスAの new
メソッドを呼び出し、返り値としてクラスAの新しいインスタンスを受け取る。もしクラスAに initialize
という名前のメソッドが定義されていると、 new
で新しくインスタンスが作られた時に、そのインスタンスのメソッドとして自動的に呼びだされる。
class Human
def initialize
puts '生まれた!'
end
end
x = Human.new
5.5. インスタンス変数¶
インスタンス変数は、それぞれのインスタンスに同じ名前で別の変数が存在し、メソッドを実行するインスタンスが持っている変数が使われる。
class Student
def initialize(n, s)
@name = n
@score = s
end
def name
@name
end
def score
@score
end
def score=(s)
@score = s
end
def compare(x)
case
when @score > x.score
"私は#{x.name}より賢い!"
when @score < x.score
"私は#{x.name}よりアホです…"
else
"私は#{x.name}と引き分け"
end
end
end
taro = Student.new('太郎', 65)
hanako = Student.new('花子', 80)
puts taro.compare(hanako) # 太郎の側から見て花子と比較する
puts hanako.compare(taro) # 花子の側から見て太郎と比較する
インスタンス変数は、他のオブジェクトから読み書きできないので、アクセス用のメソッド(上の例だと score
と score=
とか)を書く必要がある。それは面倒なので、 attr_accessor
などを使うと一行で済む。
class Student
attr_reader :name
attr_accessor :score
def initialize(n, s)
@name = n
@score = s
end
def compare(x)
case
when @score > x.score
"私は#{x.name}より賢い!"
when @score < x.score
"私は#{x.name}よりアホです…"
else
"私は#{x.name}と引き分け"
end
end
end
課題8
次のようなメソッドを持つ預金口座のクラスを定義せよ。ただし、残高より多い金額は引き出したり振り込んだりできないので、その場合はエラーメッセージを出力し、残高は変えないものとする。
残高を調べる
金額を指定して預ける
金額を指定して引き出す
相手の口座と金額を指定して振り込む
実行例は次のようになる。
a = Account.new #aの口座
a.deposit(3000) #aの口座に3000円預ける
b = Account.new #bの口座
b.deposit(1000) #bの口座に1000円預ける
b.withdraw(500) #bの口座から500円引き出す
a.transfer(b, 2000) #aの口座からbの口座に2000円振り込む
puts a.balance #aの口座残高を表示
puts b.balance #bの口座残高を表示
b.transfer(a, 5000) #bの口座からaの口座に5000円振り込む
なお、残高不足のメッセージを表示するところは、プログラム内で一箇所だけにすること。
5.6. 継承¶
元になるクラスを親クラスまたはスーパークラス、新しく作るクラスを子クラスまたはサブクラスと呼ぶ。
class Student
def initialize(n)
@name = n
end
def name
@name
end
end
class KeioStudent < Student
def university
'慶應義塾大学'
end
end
class PStudent < KeioStudent
def faculty
'総合政策学部'
end
end
class EStudent < KeioStudent
def faculty
'環境情報学部'
end
end
taro = PStudent.new('太郎')
puts "#{taro.name}は#{taro.university}#{taro.faculty}の学生です。"
課題9
上のプログラムで、 Student
クラスのメソッドとして affiliation
メソッドを定義し、その学生の大学名と学部名をつなげた文字列を返すようにせよ。( PStudent
と EStudent
に定義するのではないことに注意)
実行例はこんな感じ。
taro = PStudent.new('太郎')
hanako = EStudent.new('花子')
puts "#{taro.name}は#{taro.affiliation}の学生です。"
puts "#{hanako.name}は#{hanako.affiliation}の学生です。"
5.7. 特異メソッド¶
普通のメソッドは、あるクラスのインスタンス全部に共通だが、特定のインスタンスだけのメソッドを定義できる。
5.8. アクセス制御¶
JavaやC++の public
, protected
, private
とは意味が違うので注意。