Ruby 2.2.0 リファレンスマニュアル > ライブラリ一覧 > 組み込みライブラリ > BasicObjectクラス
クラスの継承リスト: BasicObject
特殊な用途のために意図的にほとんど何も定義されていないクラスです。 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
! self -> bool
[permalink][rdoc]オブジェクトを真偽値として評価し、その論理否定を返します。
このメソッドは self が nil または false であれば真を、さもなくば偽を返します。 主に論理式の評価に伴って副作用を引き起こすことを目的に 再定義するものと想定されています。
このメソッドを再定義しても Ruby の制御式において nil や false 以外が偽として 扱われることはありません。
例
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]オブジェクトが other と等しくないことを判定します。
デフォルトでは self == other を評価した後に結果を論理否定して返します。 このため、サブクラスで BasicObject#== を再定義しても != とは自動的に整合性が とれるようになっています。
ただし、 BasicObject#!= 自身や BasicObject#! を再定義した際には、ユーザーの責任で 整合性を保たなくてはなりません。
このメソッドは主に論理式の評価に伴って副作用を引き起こすことを目的に 再定義するものと想定されています。
[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]オブジェクトが other と等しければ真を、さもなくば偽を返します。
このメソッドは各クラスの性質に合わせて、サブクラスで再定義するべきです。 多くの場合、オブジェクトの内容が等しければ真を返すように (同値性を判定するように) 再定義 することが期待されています。
デフォルトでは Object#equal? と同じオブジェクトの同一性になっています。
例
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]各オブジェクトに対して一意な整数を返します。あるオブジェクトに対し てどのような整数が割り当てられるかは不定です。
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]__send__(name, *args) { .... } -> object
オブジェクトのメソッド name を 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]オブジェクトが other と同一であれば真を、さもなくば偽を返します。
このメソッドは2つのオブジェクトが同一のものであるかどうかを判定します。 一般にはこのメソッドを決して再定義すべきでありません。 ただし、 BasicObject の位置づけ上、どうしても再定義が必要な用途もあるでしょう。 再定義する際には自分が何をしているのかよく理解してから実行してください。
例
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]instance_eval {|obj| ... } -> object
オブジェクトのコンテキストで文字列 expr またはオブジェクト自身をブロックパラメータとするブロックを 評価してその結果を返します。
オブジェクトのコンテキストで評価するとは評価中の self をそのオブジェクトにして実行するということです。 また、文字列 expr やブロック中でメソッドを定義すればそのオブジェクトの特異メソッドが定義されます。
ただし、ローカル変数だけは、文字列 expr の評価では instance_eval の外側のスコープと、ブロックの評価ではそのブロックの外側のスコープと、共有します。
メソッド定義の中で instance_eval でメソッドを定義した場合は、囲むメソッドが実行されたときに 初めて instance_eval 内のメソッドが定義されます。これはメソッド定義のネストと同じです。 クラス/メソッドの定義/メソッド定義のネスト を参照してください。
BasicObject を継承して作ったクラス内で instance_eval する場合はトップレベルの定数や Kernel モジュールに定義されているメソッドは見えません。 これは、トップレベルの定数が Object 以下に作成されるためです。
例
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]与えられたブロックをレシーバのコンテキストで実行します。
ブロック実行中は、 self がレシーバのコンテキストになるので レシーバの持つインスタンス変数にアクセスすることができます。
例
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
method_missing(name, *args) -> object
[permalink][rdoc]呼びだされたメソッドが定義されていなかった時、Rubyインタプリタがこのメソッド を呼び出します。
呼び出しに失敗したメソッドの名前 (Symbol) が name に その時の引数が第二引数以降に渡されます。
デフォルトではこのメソッドは例外 NoMethodError を発生させます。
例
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]特異メソッドが追加された時にインタプリタから呼び出されます。
通常のメソッドの追加に対するフックには Module#method_addedを使います。
例
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]特異メソッドが Module#remove_method に より削除された時にインタプリタから呼び出されます。
通常のメソッドの削除に対するフックには Module#method_removedを使います。
例
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]特異メソッドが Module#undef_method または undef により未定義にされた時にインタプリタから呼び出されます。
通常のメソッドの未定義に対するフックには Module#method_undefined を使います。
例
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