Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
**************
オブジェクト
**************
======================
オブジェクト指向とは
======================
* `イメージで理解する「プログラミング初心者が確実に意味不明になる”オブジェクト指向プログラミング”ってなんなのさ」(ブログ「プログラミングを趣味にしたい」) `_
Rubyではすべてのデータはオブジェクトである。例えば整数のクラスは ``Integer`` 、文字列のクラスは ``String`` など。
Ruby言語に `最初から組み込まれているクラス `_ と、 `組み込みではないが標準的に用意されているクラス `_ がある。
============
クラス定義
============
* `クラス定義 `_
* `クラスとは(RubyLife) `_
同じクラス名で複数箇所に定義を書いてもよい。その場合は定義が追加されていく。
==========
メソッド
==========
* `メソッド(RubyLife) `_
メソッドを実行する時は必ず実行主体となるオブジェクト(「私」が誰かということ)があり、それは ``self`` という変数に入っている。
メソッドを呼び出す時は実行主体となるオブジェクトを指定しないといけないが、指定しない場合は ``self`` が使われる。したがって次の二つは同じ。
.. code-block:: ruby
foo()
.. code-block:: ruby
self.foo()
.. note::
Rubyに関数や演算子は無く、すべてメソッドである。関数のように使うものは ``Object`` クラスで定義されている(正確には ``Kernel`` モジュールで定義され、 ``Object`` クラスにインポートされている)。 ``Object`` はすべてのクラスのスーパークラスなので、そこで定義されたメソッドはすべてのオブジェクトでメソッド名だけ書いて使うことができる。
====================
インスタンスの生成
====================
クラスAの新しいオブジェクトを作るには、クラスAの ``new`` メソッドを呼び出し、返り値としてクラスAの新しいインスタンスを受け取る。もしクラスAに ``initialize`` という名前のメソッドが定義されていると、 ``new`` で新しくインスタンスが作られた時に、そのインスタンスのメソッドとして自動的に呼びだされる。
.. code-block:: ruby
class Human
def initialize
puts '生まれた!'
end
end
x = Human.new
==================
インスタンス変数
==================
* `インスタンス変数 `_
インスタンス変数は、それぞれのインスタンスに同じ名前で別の変数が存在し、メソッドを実行するインスタンスが持っている変数が使われる。
.. code-block:: ruby
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_manual|_ などを使うと一行で済む。
.. |attr_accessor_manual| replace:: ``attr_accessor``
.. _attr_accessor_manual: https://docs.ruby-lang.org/ja/latest/class/Module.html#I_ATTR_ACCESSOR
.. code-block:: ruby
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
.. admonition:: 課題8
:class: exercise
次のようなメソッドを持つ預金口座のクラスを定義せよ。ただし、残高より多い金額は引き出したり振り込んだりできないので、その場合はエラーメッセージを出力し、残高は変えないものとする。
* 残高を調べる
* 金額を指定して預ける
* 金額を指定して引き出す
* 相手の口座と金額を指定して振り込む
実行例は次のようになる。
.. code-block:: ruby
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円振り込む
なお、残高不足のメッセージを表示するところは、プログラム内で一箇所だけにすること。
:ref:`【解答例】 `
======
継承
======
* `クラスの継承(RubyLife) `_
元になるクラスを親クラスまたはスーパークラス、新しく作るクラスを子クラスまたはサブクラスと呼ぶ。
.. code-block:: ruby
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}の学生です。"
.. admonition:: 課題9
:class: exercise
上のプログラムで、 ``Student`` クラスのメソッドとして ``affiliation`` メソッドを定義し、その学生の大学名と学部名をつなげた文字列を返すようにせよ。( ``PStudent`` と ``EStudent`` に定義するのではないことに注意)
実行例はこんな感じ。
.. code-block:: ruby
taro = PStudent.new('太郎')
hanako = EStudent.new('花子')
puts "#{taro.name}は#{taro.affiliation}の学生です。"
puts "#{hanako.name}は#{hanako.affiliation}の学生です。"
:ref:`【解答例】 `
==============
特異メソッド
==============
* `特異メソッド定義 `_
* `結局、Rubyの特異メソッドって何なの?(ブログ「sasata299's blog」) `_
普通のメソッドは、あるクラスのインスタンス全部に共通だが、特定のインスタンスだけのメソッドを定義できる。
==============
アクセス制御
==============
* `呼び出し制限 `_
* `Ruby の private と protected 。歴史と使い分け(Qiita) `_
JavaやC++の ``public`` , ``protected`` , ``private`` とは意味が違うので注意。