クラスの概要
Rubyにおけるクラスの記述方法と、クラス内の変数やメソッドについて説明します。ここではオブジェクト指向プログラミング自体の説明は割愛します。
クラスの定義
クラスはオブジェクトの振る舞いを定義するひな型です。クラスをインスタンス化することによりオブジェクトが生成されます。次の構文で記述します。
class クラス名
#クラスの定義
end
クラス名は大文字で始めなければなりません。「クラス名.new」により、インスタンス化してオブジェクトを生成することができます。クラスの定義には、変数やメソッド、initializeメソッドを定義します。
<class1.rb>
class Greeting
def hello(str = "Ruby")
puts "Hello #{str}"
end
end
g = Greeting.new #オブジェクトを生成
g.hello("World!") #メソッドを実行(引数あり)
g.hello #メソッドを実行(引数なし)
<実行結果>
C:\ruby>ruby class1.rb
Hello World!
Hello Ruby
クラスにおけるRubyの変数
変数の種類
プログラマが定義できるRubyの変数は4種類あります。これらはそれぞれスコープ(有効範囲)が異なっており、変数の命名規則で種類を区別して宣言されます。変数のそれぞれの種類と特徴について以下に示します。
変数名 |
スコープ(有効範囲)・特徴 |
変数の命名規則 |
ローカル変数 | スコープは宣言した位置からブロック・メソッド・クラス・モジュールの終りまでの範囲 |
|
グローバル変数 | スコープはプログラム全体。どこからでも参照可能 | 先頭文字が$ |
インスタンス変数 | スコープはクラスのメソッド定義内。インスタンス化された各オブジェクトに固有の変数である。 | 先頭文字が@ |
クラス変数 | スコープはクラスの定義内全体。クラスに固有の変数である。インスタンス化された全てのオブジェクトからアクセスすることができ、値はオブジェクト間で共有される。 | 先頭文字が@@ |
インスタンス変数を使ったサンプルコードを以下に示します。
<instance_var.rb>
class Greeting
def setName(name = "Ruby")
@name = name #引数をインスタンス変数@nameに設定
end
def hello
print "Hello ", @name,"\n" #変数@nameは他のメソッドからでも参照可能
end
end
g1 = Greeting.new #オブジェクトg1を生成
g1.setName("Taro") #g1に名前を設定
g2 = Greeting.new #オブジェクトg2を生成
g2.setName("Jiro") #g2に名前を設定
g1.hello
g2.hello
<実行結果>
C:\ruby>ruby instance_var.rb
Hello Taro
Hello Jiro
インスタンス変数はオブジェクトごとに異なる値を格納できるので、それぞれのオブジェクトで異なる結果を出力しています。
上と同じサンプルコードで、インスタンス変数をクラス変数に変更したものを実行します。
<class_var.rb>
class Greeting
def setName(name = "Ruby")
@@name = name #引数をクラス変数@@nameに設定
end
def hello
print "Hello ", @@name,"\n" #変数@@nameは他のメソッドでも参照可能
end
end
g1 = Greeting.new #オブジェクトg1を生成
g1.setName("Taro") #g1に名前を設定
g2 = Greeting.new #オブジェクトg2を生成
g2.setName("Jiro") #g2に名前を設定
g1.hello
g2.hello
<実行結果>
C:\ruby>ruby class_var.rb
Hello Jiro
Hello Jiro
クラス変数はオブジェクト間で共有される変数のため、g2.setName("Jiro")を実行した際に@@nameが上書きされます。その結果、g1.helloで「Hello Jiro」が表示されます。
インスタンス変数のアクセスメソッド
クラスの中で使われているインスタンス変数は、クラスの外から直接参照・変更することができません。変数の参照や変更をするには、アクセスメソッド(セッターやゲッター)を通じて行う必要があります。そこでRubyではインスタンス変数へのアクセスを容易にするために、アクセスメソッドを自動的に生成する方法が用意されています。クラスの中で次のメソッドを呼び出すことで実現します。
メソッド名 | 機能 |
attr_reader | 参照のみ可能 |
attr_writer | 変更のみ可能 |
attr_accessor |
参照・変更が可能 |
次のサンプルコードのように宣言し使用します。
<accessor.rb>
class Greeting
attr_accessor :name #アクセスメソッドを定義
end
g = Greeting.new
g.name = "Taro" #「オブジェクト名.変数名 =」で代入
puts g.name #「オブジェクト名.変数名」で参照
<実行結果>.
C:\ruby>ruby accessor.rb
Taro
クラスにおけるRubyのメソッド
メソッドの種類
Rubyのメソッドには、関数的メソッド、インスタンスメソッド、クラスメソッドがあります。関数的メソッドとはメソッドの受け手(レシーバと呼ばれるドットの左側の部分)のないメソッドです(例えばMathモジュールのsqrt)。インスタンスメソッドとは、「クラスのインスタンス」をレシーバとするメソッドで最も一般的なメソッドです。そしてクラスメソッドとは、「クラス」をレシーバとするメソッドです(例えばFileクラスのopen)。
自作のクラスに対してクラスメソッドを定義するには以下のように宣言します。
class クラス名
def self.メソッド名
#処理
end
#または次の書き方
def クラス名.メソッド名
#処理
end
end
クラスメソッドには、クラス共通の手続きを記述します。下のサンプルコードでは、オブジェクトPersonが生成された数を返すメソッドをクラスメソッドとしています。
<class_method.rb>
class Person
@@count = 0
def initialize() #newで自動的に呼ばれるメソッド
@@count += 1 #生成されるたびにカウントアップ
end
def self.count
return @@count
end
end
person1 = Person.new
person2 = Person.new
person3 = Person.new
print Person.count, " people\n" #「クラス.メソッド」になっていることに注意
<実行結果>
C:\ruby>ruby class_method.rb
3 people
メソッドのアクセススコープ
Rubyのメソッドはアクセス制限を行うことができます。private, protected, publicの三つのレベルが用意されており、デフォルトはpublicです。
アクセス制限 | 説明 |
private |
同一クラスとそのサブクラスからのみ利用可能。 レシーバを指定して呼び出すことはできない。 |
protected | 同一クラスとそのサブクラスからのみ利用可能 |
public | どのオブジェクトからも利用可能(制限なし) |
メソッドのアクセス制御の宣言は次のように行います。
class Foo
def pub_method #publicメソッド(デフォルト)
#処理
end
protected #protectedを宣言(デフォルトをprotected変更)
def protected_method #以下は自動的にprotectedメソッド
end
private #privateを宣言(デフォルトをprivateに変更)
def private_method #以下は自動的にprivateメソッド
end
end
アクセス制御を使ったサンプルコードを示します。
<access_test.rb>
class AccessTest
def invoke_private_method #publicメソッド
private_method
end
private
def private_method #privateメソッド
puts "invoked private method."
end
end
test = AccessTest.new
test.invoke_private_method
test.private_method #クラス外から直接呼びだせないためエラー
<実行結果>
C:\ruby>ruby access_test.rb
invoked private method.
access_test.rb:14:in `<main>': private method `private_method'
called for #AccessTest:0xc43860> (NoMethodError)
initializeメソッド
インスタンスメソッドの中で「initialize」と言う名前が付けられた特殊なメソッドがあります。このメソッドはオブジェクトの初期化メソッドであり、newが呼ばれたときに自動的に呼び出されるものです。次の構文で記述します。
def initialize(引数)
#初期化処理
end
newに引数があるときは、それがinitializeメソッドの引数に渡されます。
<initialize.rb>
class Profile
def initialize(name = "No name")
@name = name
end
def name
return @name
end
end
profile = Profile.new "John"
print profile.name, "\n"
<実行結果>
C:\ruby>ruby initialize.rb
John
次に、このように定義したクラスを拡張する方法について説明します。