例:
class Foo < Super def test : end : end
文法:
class 識別子 [`<' superclass ] 式.. end
クラスを定義します。クラス名はアルファベットの大文字で始まる識別子です。 *1
クラス定義は、識別子で指定した定数へのクラスの代入になります (Ruby では、クラスもオブジェクトの一つで Classクラスの インスタンスです)。
クラスが既に定義されいるとき、さらに同じクラス名でクラス定義を書くとク ラスの定義の追加になります。ただし、元のクラスと異なるスーパークラスを 明示的に指定して定義すると、元のクラスとは異なる新たなクラスを同名で定 義することになります(このとき、クラス名の定数を上書きすることになるの で警告メッセージが出ます)。
class Foo < Array def foo end end # 定義を追加(スーパークラス Array を明示的に指定しても同じ) class Foo def bar end end # 別のクラスを定義(スーパークラスが異なるので) class Foo < String end # => warning: already initialized constant Foo
クラス定義式の中は self
がそのクラスであることと、
呼び出し制限のデフォルトが異なること以外
にトップレベルとの違いはありません。クラス定義式中には任意の式を書くこ
とができクラス定義の際に実行されます。
クラス定義はネスト(入れ子)にして定義できます。以下の例で入れ子の外側の クラス Foo と内側のクラス Bar の間には(定数 Bar が Foo の中の定数 Foo::Bar であること以外には)継承関係などの機能的な関連はまったくありま せん。
class Foo class Bar end end
クラスのネストは、意味的に関連するクラスを外側のクラス/モジュールでひ とまとまりにしたり、包含関係を表すために使用されます。
# 関連するクラスを Net というカテゴリにまとめる # このような場合は外側は普通モジュールが利用される # (Net のインスタンスがない。Net を include できるなどのため) module Net class HTTP end class FTP end end obj = Net::HTTP.new # あるいは include Net obj = HTTP.new # 以下のような使い方は組込みのクラスにも見られる # 利用者は File::Constants を include することで、 # File::RDONLY などと書かずに直接 RDONLY と書くことができる。 class File module Constants RDONLY = 0 WRONLY = 1 end include Constants end File.open("foo", File::RDONLY) # あるいは include File::Constants File.open("foo", RDONLY) # 上記はあくまでも例である。実際の File.open ではより簡便な # File.open("foo", "r") という形式が使われる
クラス定義式は値を返しません。
例:
class << obj def test : end : end
文法:
class `<<' expr 式.. end
クラス定義と同じ構文で特定のオブジェクトの機能を定義します。 この構文の内部で定義したメソッドや定数は指定したオブジェクト に対してだけ有効になります。
特異クラス定義式は、最後に評価した式の結果を返します。 最後に評価した式が値を返さない場合は nil を返します。
例:
module Foo def test : end : end
文法:
module 識別子 式.. end
モジュールを定義します。モジュール名はアルファベットの大文字 で始まる識別子です。 *2
モジュール定義は、識別子で指定した定数へのモジュールの代入に なります(Ruby では、モジュールもオブジェクトの一つで Moduleクラスのインスタンスです)。
モジュールが既に定義されいるとき、さらに同じモジュール名でモ ジュール定義を書くとモジュールの定義の追加になります。
モジュール定義式は値を返しません。
例:
def fact(n) if n == 1 then 1 else n * fact(n-1) end end
文法:
def メソッド名 [`(' [arg ['=' default]] ... [`,' `*' arg] [',' '&' arg]`)'] 式.. [rescue [error_type,..] [=> evar] [then] 式..].. [else 式..] [ensure 式..] end
この定義のある場所にメソッドを定義します。すなわち、 クラス/モジュール定義中ならばそのクラス/モジュールのメソッドを 定義します。トップレベルならばどこからでも呼べるメソッドを 定義します。このようなメソッドは結果として他の言語における 「関数」のように使えます。
メソッド名としては通常の識別子の他に、再定義可能な演算子 (例: ==, +, -など 演算子式 を参照)も指定できます。
仮引数にデフォルト式が与えられた場合、メソッド呼び出しで実 引数を省略したときのデフォルト値になります(デフォルト式の 評価は呼び出し時にメソッド定義内のコンテキストで行われます)。
最後の仮引数の直前に *
がある場合には残りの実引数は
みな配列としてこの引数に格納されます。
例:
# 引数のないメソッド。以下 end は省略 def foo end # 引数のあるメソッド def foo(arg, arg2) # デフォルト引数のあるメソッド def foo(arg = nil) # ブロックをとる def foo(arg, &block) # すべて持つ def foo(arg, arg2, arg3 = nil, *rest, &block) # 演算子形式 def ==(other) def +(other) def *(other)
最後の仮引数の直前に &
があるとこのメソッドに与えられているブロッ
クが手続きオブジェクト(Proc)としてこの引数に格納されます。これは、
イテレータを定義する方法の一つです。(イテレータを
定義する代表的な方法は yield を呼び出すことです。
他に Proc.new/proc を使う方法などもありま
す。)
ブロックが与えられなかった場合のブロック引数の値はnil
です。
*
と&
が同時に指定される場合には&
が後ろに来ます。
例: イテレータの定義
# yield を使う def foo # block_given? は、メソッドがブロックを渡されて # 呼ばれたかどうかを判定する組込み関数 if block_given? yield(1,2) end end # Proc.new を使う def bar if block_given? Proc.new.call(1,2) # proc.call(1,2) でも同じ(proc は組込み関数) end end # 応用: 引数として Proc オブジェクトとブロックの # 両方を受け付けるイテレータを定義する例 def foo(block = Proc.new) block.call(1,2) end foo(proc {|a,b| p [a,b]}) foo {|a,b| p [a,b]} # ブロック引数を使う def baz(&block) if block block.call(1,2) end end
そのほか特殊な形式をとるメソッド定義を以下に挙げます。
# 単項プラス/マイナス def +@ def -@ # 要素代入 def foo=(value) # obj.foo = value # [] と []= def [](key) # obj[key] def []=(key, value) # obj[key] = value def []=(key, key2, value) # obj[key, key2] = value # バッククォート記法 def `(arg) # `arg` または %x(arg)
バッククォート記法の実装はメソッドなのでこのように再定義が可能です。普 通はこのメソッドを再定義するべきではありませんが、まれにOS(シェル)のコ マンド実行の挙動に不具合がある場合などに利用できます*3。
通常のメソッド定義はネストできません*4。またメソッド実行時の例外を捕捉するために
begin 式と同様のrescue
, else
, ensure
節を指定できます。
メソッド定義式は値を返しません。
メソッドが呼び出されると、以下の順で式が評価されます。
rescue
節または else
節ensure
節引数のデフォルト式も含め、すべてそのメソッドのコンテキストで評価されま す。
メソッドの戻り値は return に渡した値です。return
が呼び出されなかった場合は、メソッドの本体から ensure
節実行直前
までの最後に評価した式の値を返します。
最後に評価した式が(whileなど)値を返さない式の場合は
nil
を返します。
またメソッドは定義する前に呼び出すことはできません。例えば
foo def foo print "foo\n" end
は未定義メソッドの呼び出しで例外 NameError を発生させます。
例:
def foo.test print "this is foo\n" end
文法:
def 式 `.' 識別子 [`(' [引数 [`=' default]] ... [`,' `*' 引数 ]`)'] 式.. [rescue [error_type,..] [=> evar] [then] 式..].. [else 式..] [ensure 式..] end
特異メソッドとはクラスではなくある特定のオブジェクトに固有の メソッドです。特異メソッドの定義はネストできます。
クラスの特異メソッドはそのサブクラスにも継承されます。言い替 えればクラスの特異メソッドは他のオブジェクト指向システムにお けるクラスメソッドの働きをすることになります。
特異メソッド定義式は値を返しません。
Ruby におけるクラスメソッドとはクラスの特異メソッドのことです。Ruby で は、クラスもオブジェクトなので、普通のオブジェクトと同様に特異メソッド を定義できます。
したがって、何らかの方法でクラスオブジェクトにメソッドを定義すれば、そ れがクラスメソッドとなります。具体的には以下のようにして定義することが 出来ます(モジュールも同様です)。
# 特異メソッド方式。 class Hoge def Hoge.foo end end # クラス定義の外でも良い def Hoge.bar end # 以下のようにすればクラス名が変わってもメソッド部の変更が不要 class Hoge def self.baz 'To infinity and beyond!' end end # 特異クラス方式。複数のメソッドを一度に定義するとき向き class << Hoge def bar 'bar' end end # モジュールをクラスに extend すれば、モジュールのインスタンス # メソッドがクラスメソッドになる module Foo def foo end end class Hoge extend Foo end
extend
については、Object#extend を参照して
ください。
メソッドは public
、private
、protected
の三通りの
呼び出し制限を持ちます。
public
に設定されたメソッドは制限なしに呼び出せます。
private
に設定されたメソッドは関数形式でしか呼び出せません。
protected
に設定されたメソッドは、そのメソッドが定義された
クラスおよびその下位クラスのインスタンスからしか呼び出せません。
デフォルトでは def
式がクラス定義の外にあれば private
、
クラス定義の中にあれば public
に定義します。これは
Module#public、Module#private、
Module#protected を用いて変更できます。ただし
initializeという名前のメソッドは定義する場所に関係なく常に
private
になります。
例:
def foo # デフォルトは private end class C def bar # デフォルトは public end def ok # デフォルトは public end private :ok # …だが、ここで private に変わる def initialize # initialize は private end end
例:
alias foo bar alias :foo :bar alias $MATCH $&
文法:
alias 新メソッド名 旧メソッド名 alias 新グローバル変数名 旧グローバル変数名
メソッドあるいはグローバル変数に別名をつけます。メソッド名に
は識別子そのものか Symbol を指定します(obj.method のよ
うな式を書くことはできません)。alias
の引数はメソッド
呼び出し等の一切の評価は行われません。
メソッドの定義内で別名を付けるにはModuleクラスのメソッド Module#alias_method を利用して下さい。
別名を付けられたメソッドは、その時点でのメソッド定義を引き継 ぎ、元のメソッドが再定義されても、再定義前の古いメソッドと同 じ働きをします。あるメソッドの動作を変え、再定義するメソッド で元のメソッドの結果を利用したいときなどに利用されます。
# メソッド foo を定義 def foo "foo" end # 別名を設定(メソッド定義の待避) alias :_orig_foo :foo # foo を再定義(元の定義を利用) def foo _orig_foo * 2 end p foo # => "foofoo"
グローバル変数の alias は一方の変更が他方に反映され、まった く同じ変数であるかのようになります。添付ライブラリの importenv.rb はこのことを利用して組込み変数 に英 語名をつけます。 *5
# 特殊な変数のエイリアスは一方の変更が他方に反映される $_ = 1 alias $foo $_ $_ = 2 p [$foo, $_] # => [2, 2] # こちらは通常の変数のエイリアスで本当の意味での # エイリアスにはならない。これは、version 1.6 ま # での制限 $bar = 3 alias $foo $bar $bar = 4 p [$foo, $bar] # => [3, 4]
ただし、正規表現の部分文字列に対応する変数
$1
,$2
, ... には別名を付けることができません。ま
た、インタプリタに対して重要な意味のあるグローバル変数
(組込み変数を参照)を再定義すると動作に支障を来す場合が
あります。
alias
式は nil を返します。
例:
undef bar
文法:
undef メソッド名[, メソッド名[, ...]]
メソッドの定義を取り消します。メソッド名には識別子そのもの
か Symbol を指定します(obj.method のような式を書くことはできません)。
undef
の引数はメソッド呼び出し等の一切の評価は行われません。
メソッドの定義内で定義を取り消すにはModuleクラスのメソッ ド Module#undef_method を利用して下 さい。
undef
のより正確な動作は、メソッド名とメソッド定義との
関係を取り除き、そのメソッド名を特殊な定義と関連づけます。この状態の
メソッドの呼び出しは例えスーパークラスに同名のメソッドがあっても例外
NameError を発生させます。
(一方、メソッド
Module#remove_method は、関係を取
り除くだけです。この違いは重要です)。
alias
による別名定義と
undef
による定義取り消しによってクラスのインタフェー
スをスーパークラスと独立に変更することができます。ただし、メ
ソッドがselfにメッセージを送っている場合もあるので、よく注意
しないと既存のメソッドが動作しなくなる可能性があります。
undef
式は nil を返します。
例:
defined? print defined? File.print defined?(foobar) defined?($foobar) defined?(@foobar) defined?(Foobar)
文法:
defined? 式
式が定義されていなければ、偽を返します。定義されていれば式の種別 を表す文字列を返します。
定義されていないメソッド、undef されたメソッド、
Module#remove_method により削除さ
れたメソッドのいずれに対しても defined?
は偽を返します。
特別な用法として以下があります。
defined? yield
yield の呼び出しが可能なら真(文字列 "yield")を返します。 block_given? と同様にメソッドがブロック付きで呼ばれたか を判断する方法になります。
defined? super
super の実行が可能なら真(文字列 "super")を返します。
defined? a = 1 p a # => nil
"assignment" を返します。実際に代入は行いませんがローカル変数は定義されます。
/(.)/ =~ "foo" p defined? $& # => "$&" p defined? $1 # => "$1" p defined? $2 # => nil
大文字で始まるメソッド名に対しては ()
を明示しなければ定数の判定
を行ってしまいます。
def Foo(a,b) end p defined? Foo # => nil p defined? Foo() # => "method" Foo = 1 p defined? Foo # => "constant"
以下は、defined? が返す値の一覧です。
*1ruby 1.7 feature: version 1.7 では、rescue/ensure 節を指定で
きます
*2ruby 1.7 feature: version 1.7 では、rescue/ensure 節を指定で
きます
*3 実際の応用例が
ruby-talk:10006[外部],ruby-dev:12829[外部]にあります
*4ruby 1.7 feature: 1.7 以
降ネスト可能になりました
*5あらい 2001-11-04: 実際には特定の組込み変数だけが
ここに書いた通りの挙動になる。version 1.7 ではこの制
限は取り除かれている