method_missing
が同じ順で捜されます.
Module Indexed
def [](n)
to_a[n]
end
end
Class String
include Indexed
end
p String.ancestors # [String, Indexed, Enumerable, Comparable, Object, Kernel]
p "abcde".gsub!(/./, "\\&\n")[1]
は,残念ながら期待するように"b\n"を返してくれず,10を返してきます.
[]がStringクラスで捜され,Indexedで定義されたものを捜し出す前に
マッチしてしまうからです.Class Stringで直接[]を再定義すれば,
期待どおりになります.
+
や-
は演算子ですか
+
や-
などは演算子ではなくメソッド呼び出しです.したがって
オーバーロードすることもできます.
class MyString < String
def +(other)
print super(other)
end
end
ただし,以下のもの及びこれらを組み合わせたもの(!=,!~)は制御構造であり,
オーバーロードできません.
=, .., ..., !, not, &&, and, |, or, ~, ::
単項演算子をオーバーロード(もしくは定義)するには,メソッド名として
+@
や-@
を使います.
=
は,インスタンス変数へのアクセスメソッドとして,
クラス定義の中で次のようにメソッドを定義することができます.
また,+
や-
なども定義することにより,+=
などの自己代入演算も可能になります.
def attribute=(val)
@attribute = val
end
def writeln(str)
print(str, "\n")
end
writeln("Hello, World!")
のように一見関数のように見えるものも,Object
クラスに定義された
メソッドであり,隠されたレシーバーself
に送られているというわけです.
したがってRubyを純粋なオブジェクト指向言語と呼ぶことができます.
self
が何であっても同じ結果を返すメソッドは,
レシーバーを意識する必要がありませんので,関数と考えてもいいという
ことになります.
Module#attr
,attr_reader
,attr_writer
,
attr_accessor
を参照してください.
もちろん,自分でメソッドを定義して参照することもできます.
method=
の形のメソッド定義は,method
と=
の間に
空白をいれることができませんが,メソッド呼出しの時には,空白をいれる
ことが可能ですし,+
,-
などのメソッドが定義されていれば,
+=
,-=
などの自己代入も行えます.
Object#instance_eval
を使えば,直接参照することもできます.
private
とprotected
の違いが分かりません
private
の意味は,メソッドを関数形式でだけ呼び出せるようにし,
レシーバー形式では呼び出せないようにするという意味です.したがって,
可視性がprivate
なメソッドは,自クラス及びサブクラスからしか参照
できません.
protected
も同様に,自クラス及びサブクラスからしか参照できませんが,
関数形式でもレシーバー形式でも呼び出せます.
attr
メソッドを使うことで外部からみると
変数にアクセスしているかのように振舞わせることが可能です.
class Foo
def initialize(str)
@name = str
end
attr("name")
# これはこういうことです.
# def name
# return @name
# end
end
foo = Foo.new("Tom")
print foo.name, "\n" # Tom
attr(name, public)
で省略可能な二番目の引数にTRUE
を指定するこ
とで書き込みメソッドを提供することも可能です.
class Foo
def initialize(str)
@name = str
end
attr("name", true)
# これはこういうことです.
# def name
# return @name
# end
# def name=(str)
# @name = str
# end
end
foo = Foo.new("Tom")
foo.name = "Jim"
print foo.name, "\n" # Jim
Module#attr_reader
, attr_writer
, attr_accessor
も
参照してください.
class Foo
def test
print "hello\n"
end
private :test
end
foo = Foo.new
foo.test
# -> test.rb:9: private method `test' called for #<Foo:0x400f3eec>(Foo)
クラスメソッドをprivateにするにはprivate_class_method
を使います.
class Foo
def Foo.test
print "hello\n"
end
private_class_method :test
end
Foo.test
# -> test.rb:8: private method `test' called for Foo(Class)
同様にpublic
,public_class_method
を用いることでメソッドを
publicにすることができます.
super
がArgumentError
になりますが
super
と呼び出すと,引数がすべて渡されますので,
引数の数が合わないとArgumentError
になります.異なる数の引数を
指定するには,super()
に引数を指定してやります.
super
は,1段上の同名のメソッドを呼び出します.それより上の同名の
メソッドを呼び出すには,あらかじめそのメソッドをaliasしておきます.
super
が使えます.再定義する前にalias
しておくと,元の定義が保たれます.
Kernel
の特異メソッドとしても呼べます.
def foo(str)
str.sub!(/foo/, "baz")
end
obj = "foo"
foo(obj)
print obj
# -> "baz"
この場合,引数となったオブジェクトが変更されています.でも,これは,プログラム
の中で必要があって副作用のあるメッセージをオブジェクトに対し
て送っているので当たり前です.
return 1, 2, 3
とすると配列が返されます.つまり,
return [1, 2, 3]
とするのと同じです.
def foo
return 20, 4, 17
end
a, b, c = foo
print "a:", a, "\n" # -> a:20
print "b:", b, "\n" # -> b:4
print "c:", c, "\n" # -> c:17
こんなことができるわけです.