プログラミング入門(4)〜クラスの概念
下記のページを参考にプログラミングの勉強を行います。
クラスとは - クラスの概念 - Ruby入門
クラスの定義とオブジェクトの作成 - クラスの概念 - Ruby入門
インスタンスメソッド - クラスの概念 - Ruby入門
インスタンス変数 - クラスの概念 - Ruby入門
initializeメソッド - クラスの概念 - Ruby入門
アクセスメソッド - クラスの概念 - Ruby入門
定数 - クラスの概念 - Ruby入門
クラス変数 - クラスの概念 - Ruby入門
クラスとは
クラスとは
クラスは次のようなもの。
class Car def initialize(carname) @name = carname end def dispName print(@name) end end
オブジェクト指向でないプログラムでは、行いたい処理を順に列挙していくが、オブジェクト指向ではまず何を行う物体の設計図を作成し、設計図から物体(オブジェクト)を作成し、その物体に処理をさせる。
クラスは物体(オブジェクト)を作成する元になる設計図であり、作成する物体がどのようなものなのかを定義する。
定義したクラスからオブジェクトを作成し、そのオブジェクトに実際の処理をさせる。
サンプルプログラム
class Car def initialize(carname) @name = carname end def dispName print(@name) end end car = Car.new("crown") car.dispName
「車」の設計図であるクラスを定義し、クラスからオブジェクトを作成した後で、オブジェクトに対して名前を画面に表示させている。
クラスの定義とオブジェクトの作成
クラスの定義
クラスの定義は次のように行う。
class クラス名 end
クラスは「class」から始まり「end」で終わりとなる。そしてクラスにはクラス名を指定する。
クラス名はクラスを識別するための名前で、大文字のアルファベットから始まる。
例えば「Car」というクラスを定義は次のように行う。
class Car end
オブジェクトの作成
クラスはあくまで設計図なので、実際に何かを行わせるには、クラスからオブジェクトを作成する必要がある。すべてのクラスにはいくつかのクラスに対する動作を行わせるクラスメソッドが用意されている。
ここではクラスからオブジェクトを作成するための「new」メソッドを使用してみる。
class クラス名 end 変数名 = クラス名.new()
クラスからオブジェクトを作成するには、クラス名に対して「new」メソッドを実行する。メソッドはクラス名の後にドット「.」をつけて記述する。そして作成されたオブジェクトを格納するための変数を指定する。
class Car end car1 = Car.new()
クラスは設計図なので設計図から複数のオブジェクトを作成することができる。作成されたオブジェクトはそれぞれクラスに基づいた動作をするが、別々に操作することができる。
class Car end car1 = Car.new() car2 = Car.new()
サンプルプログラム
class Car def initialize(carname) @name = carname end def dispName print(@name, "\n") end end car1 = Car.new("crown") car1.dispName car2 = Car.new("civic") car2.dispName
今回のサンプルでは「車」の設計図であるクラスを定義し、クラスから2つのオブジェクトを作成している。オブジェクトの元になっているクラスは同じだが、異なる初期化処理を行っているため、同じメソッドを実行させても別の動作を行う。
インスタンスメソッド
インスタンスメソッド
クラスは何かを行うための設計図。そこで具体的に何をさせたいかをクラスの中に記述していく必要がある。その処理を記述するのがメソッド。
メソッドは実行する一連の処理をまとめたもの。
ただし、通常のメソッドがプログラムからいつでも呼び出せるのに対し、クラス内に記述されたメソッドはクラスから作成されたオブジェクトしか呼び出すことができない。このようなメソッドをインスタンスメソッドと呼ぶ。
class クラス名 def メソッド名(引数1, 引数2, ...) 処理 end end
下記は簡単なインスタンスメソッドの例。
引数がないメソッドの場合は括弧を省略してもかまわない。
class Car def dispClassname print("Car class\n") end def dispString(str) print(str,"\n") end end
インスタンスメソッドの呼び出し
定義されたインスタンスメソッドはクラスのオブジェクトから呼び出すことができる。
class Car def dispClassname print("Car class\n") end def dispString(str) print(str,"\n") end end car = Car.new car.dispClassname car.dispString("crowm")
オブジェクトからメソッドを呼び出すには、オブジェクトの後にドット「.」をつけてメソッド名を記述する。引数がある場合は括弧の後に引数をカンマで列挙して記述する。引数がない場合はメソッド名だけでかまわない。
オブジェクト名.メソッド名(引数1, 引数2, ...) オブジェクト名.メソッド名
またドットの代わりにコロン「:」を2つ続けて次のように記述することもできる。
オブジェクト名::メソッド名(引数1, 引数2, ...) オブジェクト名::メソッド名
インスタンス変数
インスタンス変数
オブジェクトの中で値を保存しておくために利用されるのがインスタンス変数。
ローカル変数をメソッド内で使用することも可能ですが、ローカル変数は一度メソッドを抜けてしまえば値は消えてしまう。
インスタンス変数はクラス内の全メソッドで共通して使用することができる。
最初にどこかのメソッドで使用された時点でインスタンス変数は作成され、一度作成されたインスタンス変数は他のメソッドで値を取り出したり格納したりすることができるようになる。
また、インスタンス変数はクラスから作成されるオブジェクトごとに固有のものとなる。例えば、一つのオブジェクトの中でインスタンス変数に格納された値と、別のオブジェクトの中でインスタンス変数に格納された値は別のものとなる。
インスタンス変数の変数名は「@name」などのように「@」で始まる。ローカル変数などと同じく値が格納された時点から使用できるようになる。
class クラス名 def メソッド名 @name = 値 end end
インスタンス変数はインスタンス変数が使用可能になったインスタンスメソッド以外のインスタンスメソッド内でもしいようすることができる。
class Car def setName(str) @name = str end def dispName() print(@name,"\n") end end car = Car.new car.setName("crowm") car.dispName()
上記の場合は「setName」メソッドによってインスタンス変数「@name」に値が格納され、「dispName」メソッドのよってインスタンス変数「@name」に格納されている値を表示している。
インスタンス変数の割り当て
クラスからは複数のオブジェクトを作成することができるが、インスタンス変数はオブジェクト毎に異なる値を割り当てることができる。
class Car def setName(str) @name = str end def dispName() print(@name,"\n") end end car1 = Car.new car1.setName("crowm") car2 = Car.new car2.setName("civic") car1.dispName() car2.dispName()
上記のプログラムでは「car1」オブジェクト「car2」オブジェクトには別々のインスタンス変数「@name」が割り当てられているので、それぞれのオブジェクトに対してメソッドを使って値を格納した場合、上書きされることなく異なる値を格納することができる。
initializeメソッド
initializeメソッド
インスタンスメソッドの中で「initialize」という名前が付けられたメソッドは特殊なメソッドで、このメソッドをクラス内に記述した場合には、オブジェクトが作成されるときに自動的に呼び出される。
※Javaなどのコンストラクタと同じ。
「initialize」メソッドを使うことでオブジェクトを作成時に必ず実行したい処理をメソッドを呼び出すことなく実行することができる。
次の例では「initialize」メソッドの中でインスタンス変数を初期化している。
class Car def initialize() @name = "未定義" end end car = Car.new()
これは「initialize」メソッドを使わずに通常のインスタンスメソッドを使って次のように記述した場合と同じ。
class Car def init() @name = "未定義" end end car = Car.new() car.init()
「initialize」メソッドに引数を指定する
他のメソッドと同じく「initialize」メソッドも呼び出すときに引数を指定して呼び出すことで、メソッドに値を渡すことができるが、「initialize」メソッドは自動的に呼び出されるメソッドなので、「initialize」メソッドに渡す値はクラスメソッドの「new」メソッドの引数に指定する。
class Car def initialize(carname) @name = carname end end car = Car.new("civic")
また、他のメソッドと同じく引数に初期値を設定することも可能。
class Car def initialize(carname="未定義") @name = carname end end car1 = Car.new("civic") car2 = Car.new()
サンプルプログラム
class Car def initialize(carname="未定義") @name = carname end def dispName() print(@name, "\n") end end car1 = Car.new("civic") car2 = Car.new() car1.dispName() car2.dispName()
アクセスメソッド
アクセスメソッド
クラスの中で使われているインスタンス変数はクラスの外からは参照したり値を変更したりすることができない。参照する場合も変更したい場合もインスタンスメソッドを経由して行う必要がある。
class Car def initialize(carname="未定義") @name = carname end def getName() return @name end def setName(newName) @name = newName end end car = Car.new() car.setName("civic") print(car.getName())
このようにメソッドを定義することでオブジェクトからインスタンス変数の参照や更新が行えるが、多くのインスタンス変数があるが愛はメソッドを定義するだけでも大変。
そこで、インスタンス変数への参照屋更新が簡単に行えるようにアクセスメソッドと呼ばれるものが用意されている。
用意されているアクセスメソッドは次の3つ
attr_reader:変数名 …参照が可能
attr_writer:変数名 …更新が可能
attr_accessor:変数名 …参照と更新が可能
使い方は次のようになる。
class Car def initialize(carname="未定義") @name = carname end attr_accessor:name end
上記のように対象となるインスタンス変数名に対して「attr_reader」「attr_writer」「attr_accessor」のいずれかを使って上記のように記述することでインスタンス変数の参照や更新用のメソッドを個別に定義する代わりとなる。
サンプルプログラム
class Car def initialize(carname="未定義") @name = carname end attr_accessor :name end car = Car.new() car.name = "civic" print(car.name)
「オブジェクト名.変数名」で参照したり更新したりが直接行える。
クラス外からインスタンス変数が直接操作できるようになったわけではなく、参照や更新が行えるメソッドが自動的に作成されたと考えること。
定数
定数
クラス内で定数を定義することができる。
定数はアルファベットの大文字で始まる変数名に対して一度だけ値を格納することができる。
class Reji SHOUHIZEI = 0.05 def initialize(init=0) @sum = init end def kounyuu(kingaku) @sum += kingaku end def goukei() return @sum * (1 + SHOUHIZEI) end end reji = Reji.new(0) reji.kounyuu(100) reji.kounyuu(80) print(reji.goukei())
上記の例ではクラス「Rei」内で定数「SHOUHIZEI」を定義している。なお、クラス内の場合もメソッドの中では定数は定義できない。
クラス外から定数の参照
クラス内で定義された定数は、次のように記述することでクラス外から参照することができる。
クラス名::定数名
なお、「::」はメソッドの場合の呼び出しでも使用できるが、メソッドのように「.」だけを使って「クラス名.定数名」のようには使用できない。
サンプルプログラム
class Reji SHOUHIZEI = 0.05 def initialize(init=0) @sum = init end def kounyuu(kingaku) @sum += kingaku print("お買い上げ:", kingaku, "\n") end def goukei() return @sum * (1 + SHOUHIZEI) end end reji = Reji.new(0) reji.kounyuu(100) reji.kounyuu(80) print("合計金額:", reji.goukei(), "\n") print("消費税率:", Reji::SHOUHIZEI)
クラス変数
クラス変数
クラス内で使用するインスタンス変数はクラスから作成されたオブジェクト毎に異なる値を格納できるものであったのに対して、クラス変数はクラスから作成されたすべてのオブジェクトで共有される変数となる。
すべてのオブジェクトで共有されるため、あるオブジェクトを使ってクラス変数の値を変更した場合は、別のオブジェクトでクラス変数を参照すると更新された値を取得することになる。
クラス変数の変数名は「@@name」などのように「@@」で始まる。
ローカル変数などと同じく値が格納された時点から使用できるようになる。
class クラス名 @@name = 値 end
クラス変数はメソッド内ではなく、定数と同じクラス内のメソッド内ではない場所で定義する。
サンプルプログラム
class Car @@count = 0 def initialize(carname="未定義") @name = carname @@count += 1 end def getCount() return @@count end end car1 = Car.new("crown") car2 = Car.new("civic") car3 = Car.new("alto") print("現在生成されたオブジェクト数:", car1.getCount())
上記のサンプルの場合、まず「@@count = 0」でクラス変数の初期化が行われている。この初期化は最初のオブジェクトが作成されたときに実行されるが、それ以降のオブジェクトが作成された時には実行されない。
次に「initialize」メソッドの中でクラス変数の値を「+1」している。これはオブジェクトが実行される度に実行されるので、オブジェクトが作成されるたびにクラス変数の値が増加していくことになる。
今回は「car1」オブジェクトを使ってクラス変数の値を取得したが、他のオブジェクトを使ってクラス変数を取得しても同じ結果になる。