要約
特殊な用途のために意図的にほとんど何も定義されていないクラスです。 Objectクラスの親にあたります。Ruby 1.9 以降で導入されました。
性質
BasicObject クラスは Object クラスからほとんどのメソッドを取り除いたクラスです。
Object クラスは様々な便利なメソッドや Kernel から受け継いだ関数的メソッドを多数有しています。これに対して、 BasicObject クラスはオブジェクトの同一性を識別したりメソッドを呼んだりする最低限の機能の他は一切の機能を持っていません。
用途
基本的にはほぼすべてのクラスの親は Object と考えて差し支えありません。しかし、ある種のクラスを定義する際には Object クラスは持っているメソッドが多すぎる場合があります。
例えば、 BasicObject#method_missingを利用して Proxy パターンを実装する場合にはObject クラスに定義済みのメソッドはプロクシできないという問題が発生します。このような場合に Object ではなく BasicObject から派生して問題を解決できます。
注意
通常のクラスは Object またはその他の適切なクラスから派生すべきです。真に必要な場合にだけ BasicObject から派生してください。
例
class Proxy < BasicObject
def initialize(target)
@target = target
end
def method_missing(message, *args)
@target.__send__(message, *args)
end
end
proxy = Proxy.new("1")
proxy.to_i #=> 1
目次
- インスタンスメソッド
- privateメソッド
インスタンスメソッド
! self -> bool
[permalink][rdoc][edit]-
オブジェクトを真偽値として評価し、その論理否定を返します。
このメソッドは self が nil または false であれば真を、さもなくば偽を返します。主に論理式の評価に伴って副作用を引き起こすことを目的に再定義するものと想定されています。
このメソッドを再定義しても Ruby の制御式において nil や false 以外が偽として扱われることはありません。
- [RETURN]
- オブジェクトが偽であれば真、さもなくば偽
class NegationRecorder < BasicObject def initialize @count = 0 end attr_reader :count def ! @count += 1 super end end recorder = NegationRecorder.new !recorder !!!!!!!recorder puts 'hoge' if !recorder puts recorder.count #=> 3
class AnotherFalse < BasicObject def ! true end end another_false = AnotherFalse.new # another_falseは*真* puts "another false is a truth" if another_false #=> "another false is a truth"
self != other -> bool
[permalink][rdoc][edit]-
オブジェクトが other と等しくないことを判定します。
デフォルトでは self == other を評価した後に結果を論理否定して返します。このため、サブクラスで BasicObject#== を再定義しても != とは自動的に整合性がとれるようになっています。
ただし、 BasicObject#!= 自身や BasicObject#! を再定義した際には、ユーザーの責任で整合性を保たなくてはなりません。
このメソッドは主に論理式の評価に伴って副作用を引き起こすことを目的に再定義するものと想定されています。
- [PARAM] other:
- 比較対象となるオブジェクト
[SEE_ALSO] BasicObject#==, BasicObject#!
class NonequalityRecorder < BasicObject def initialize @count = 0 end attr_reader :count def !=(other) @count += 1 super end end recorder = NonequalityRecorder.new recorder != 1 puts 'hoge' if recorder != "str" p recorder.count #=> 2
self == other -> bool
[permalink][rdoc][edit]-
オブジェクトが other と等しければ真を、さもなくば偽を返します。
このメソッドは各クラスの性質に合わせて、サブクラスで再定義するべきです。多くの場合、オブジェクトの内容が等しければ真を返すように (同値性を判定するように) 再定義することが期待されています。
デフォルトでは Object#equal? と同じオブジェクトの同一性になっています。
- [PARAM] other:
- 比較対象となるオブジェクト
- [RETURN]
- other が self と同値であれば真、さもなくば偽
class Person < BasicObject def initialize(name, age) @name = name @age = age end end tanaka1 = Person.new("tanaka", 24) tanaka2 = Person.new("tanaka", 24) tanaka1 == tanaka1 #=> true tanaka1 == tanaka2 #=> false
[SEE_ALSO] BasicObject#equal?, Object#==, Object#equal?, Object#eql?
__id__ -> Integer
[permalink][rdoc][edit]-
各オブジェクトに対して一意な整数を返します。あるオブジェクトに対してどのような整数が割り当てられるかは不定です。
Object#object_id と同じですが、#object_id は BasicObject にはない事に注意してください。
# frozen_string_literal: false obj = Object.new obj.object_id == obj.__id__ # => true Object.new.__id__ == Object.new.__id__ # => false (21 * 2).__id__ == (21 * 2).__id__ # => true "hello".__id__ == "hello".__id__ # => false "hi".freeze.__id__ == "hi".freeze.__id__ # => true
[SEE_ALSO] Object#object_id, [ruby-dev:42840]
__send__(name, *args) -> object
[permalink][rdoc][edit]__send__(name, *args) { .... } -> object
-
オブジェクトのメソッド name を args を引数にして呼び出し、メソッドの結果を返します。
ブロック付きで呼ばれたときはブロックもそのまま引き渡します。
- [PARAM] name:
- 呼び出すメソッドの名前。 Symbol または文字列で指定します。
- [PARAM] args:
- メソッドに渡す任意個の引数
class Mail def delete(*args) "(Mail#delete) - delete " + args.join(',') end def send(name, *args) "(Mail#send) - #{name} #{args.join(',')}" end end mail = Mail.new mail.send :delete, "gentle", "readers" # => "(Mail#send) - delete gentle,readers" mail.__send__ :delete, "gentle", "readers" # => "(Mail#delete) - delete gentle,readers"
[SEE_ALSO] Object#send
equal?(other) -> bool
[permalink][rdoc][edit]-
オブジェクトが other と同一であれば真を、さもなくば偽を返します。
このメソッドは2つのオブジェクトが同一のものであるかどうかを判定します。一般にはこのメソッドを決して再定義すべきでありません。ただし、 BasicObject の位置づけ上、どうしても再定義が必要な用途もあるでしょう。再定義する際には自分が何をしているのかよく理解してから実行してください。
- [PARAM] other:
- 比較対象となるオブジェクト
- [RETURN]
- other が self 自身であれば真、さもなくば偽
original = "a" copied = original.dup substituted = original original == copied #=> true original == substituted #=> true original.equal? copied #=> false original.equal? substituted #=> true
[SEE_ALSO] Object#equal?, Object#==, Object#eql?
instance_eval(expr, filename = "(eval)", lineno = 1) -> object
[permalink][rdoc][edit]instance_eval {|obj| ... } -> object
-
オブジェクトのコンテキストで文字列 expr またはオブジェクト自身をブロックパラメータとするブロックを評価してその結果を返します。
オブジェクトのコンテキストで評価するとは評価中の self をそのオブジェクトにして実行するということです。また、文字列 expr やブロック中でメソッドを定義すればそのオブジェクトの特異メソッドが定義されます。
ただし、ローカル変数だけは、文字列 expr の評価では instance_eval の外側のスコープと、ブロックの評価ではそのブロックの外側のスコープと、共有します。
メソッド定義の中で instance_eval でメソッドを定義した場合は、囲むメソッドが実行されたときに初めて instance_eval 内のメソッドが定義されます。これはメソッド定義のネストと同じです。 クラス/メソッドの定義/メソッド定義のネスト を参照してください。
BasicObject を継承して作ったクラス内で instance_eval する場合はトップレベルの定数や Kernel モジュールに定義されているメソッドは見えません。これは、トップレベルの定数が Object 以下に作成されるためです。
- [PARAM] expr:
- 評価する文字列です。
- [PARAM] filename:
- 文字列を指定します。ファイル filename に文字列 expr が書かれているかのように実行されます。スタックトレースの表示などを差し替えることができます。
- [PARAM] lineno:
- 整数を指定します。行番号 lineno から文字列 expr が書かれているかのように実行されます。スタックトレースの表示などを差し替えることができます。
class Foo def initialize data @key = data end private def do_fuga p 'secret' end end some = Foo.new 'XXX' some.instance_eval{p @key} #=> "XXX" some.instance_eval{do_fuga } #=> "secret" # private メソッドも呼び出せる some.instance_eval 'raise' # ..:10: (eval):1: (RuntimeError) messg = 'unknown' some.instance_eval 'raise messg','file.rb',999 # file.rb:999: unknown (RuntimeError)
class Bar < BasicObject def call1 instance_eval("::ENV.class") end def call2 instance_eval("ENV.class") end end bar = Bar.new bar.call1 # => Object bar.call2 # raise NameError
[SEE_ALSO] Module#module_eval, Kernel.#eval, BasicObject#instance_exec
instance_exec(*args) {|*vars| ... } -> object
[permalink][rdoc][edit]-
与えられたブロックをレシーバのコンテキストで実行します。
ブロック実行中は、 self がレシーバのコンテキストになるのでレシーバの持つインスタンス変数にアクセスすることができます。
- [PARAM] args:
- ブロックパラメータに渡す値です。
class KlassWithSecret def initialize @secret = 99 end end k = KlassWithSecret.new # 以下で x には 5 が渡される k.instance_exec(5) {|x| @secret + x } #=> 104
[SEE_ALSO] Module#class_exec, Module#module_exec, BasicObject#instance_eval
privateメソッド
method_missing(name, *args) -> object
[permalink][rdoc][edit]-
呼びだされたメソッドが定義されていなかった時、Rubyインタプリタがこのメソッドを呼び出します。
呼び出しに失敗したメソッドの名前 (Symbol) が name にその時の引数が第二引数以降に渡されます。
デフォルトではこのメソッドは例外 NoMethodError を発生させます。
- [PARAM] name:
- 未定義メソッドの名前(シンボル)です。
- [PARAM] args:
- 未定義メソッドに渡された引数です。
- [RETURN]
- ユーザー定義の method_missing メソッドの返り値が未定義メソッドの返り値であるかのように見えます。
class Foo def initialize(data) @data = data end def method_missing(name, lang) if name.to_s =~ /\Afind_(\d+)_in\z/ if @data[lang] p @data[lang][$1.to_i] else raise "#{lang} unknown" end else super end end end dic = Foo.new({:English => %w(zero one two), :Esperanto => %w(nulo unu du)}) dic.find_2_in :Esperanto #=> "du"
[注意] このメソッドを override する場合は対象のメソッド名に対して Object#respond_to? が真を返すようにしてください。そのためには、Object#respond_to_missing? も同様に override する必要があります。
[SEE_ALSO] Object#respond_to?, Object#respond_to_missing?
singleton_method_added(name) -> object
[permalink][rdoc][edit]-
特異メソッドが追加された時にインタプリタから呼び出されます。
通常のメソッドの追加に対するフックには Module#method_addedを使います。
- [PARAM] name:
- 追加されたメソッド名が Symbol で渡されます。
class Foo def singleton_method_added(name) puts "singleton method \"#{name}\" was added" end end obj = Foo.new def obj.foo end #=> singleton method "foo" was added
[SEE_ALSO] Module#method_added,BasicObject#singleton_method_removed,BasicObject#singleton_method_undefined
singleton_method_removed(name) -> object
[permalink][rdoc][edit]-
特異メソッドが Module#remove_method により削除された時にインタプリタから呼び出されます。
通常のメソッドの削除に対するフックには Module#method_removedを使います。
- [PARAM] name:
- 削除されたメソッド名が Symbol で渡されます。
class Foo def singleton_method_removed(name) puts "singleton method \"#{name}\" was removed" end end obj = Foo.new def obj.foo end class << obj remove_method :foo end #=> singleton method "foo" was removed
[SEE_ALSO] Module#method_removed,BasicObject#singleton_method_added,BasicObject#singleton_method_undefined
singleton_method_undefined(name) -> object
[permalink][rdoc][edit]-
特異メソッドが Module#undef_method または undef により未定義にされた時にインタプリタから呼び出されます。
通常のメソッドの未定義に対するフックには Module#method_undefined を使います。
- [PARAM] name:
- 未定義にされたメソッド名が Symbol で渡されます。
class Foo def singleton_method_undefined(name) puts "singleton method \"#{name}\" was undefined" end end obj = Foo.new def obj.foo end def obj.bar end class << obj undef_method :foo end obj.instance_eval {undef bar} #=> singleton method "foo" was undefined # singleton method "bar" was undefined
[SEE_ALSO] Module#method_undefined,BasicObject#singleton_method_added,BasicObject#singleton_method_removed , クラス/メソッドの定義/undef