Rubyの遅延評価
概要
Ruby ではオブジェクトを作成する必要がある可能性がありますが、それはわかりません。また、オブジェクトの作成にはコストがかかる可能性があるため、あまり熱心に作成するつもりはありません。これは明らかに遅延読み込みのケースだと思います。誰かがメッセージを送信したときにのみ作成されないオブジェクトを定義するにはどうすればよいですか?オブジェクトはブロック内に作成されます。 Rubyで単純な遅延ロード/初期化を行う方法はありますか?これらは、オブジェクトの遅延初期化のさまざまなケースに対してさまざまなソリューションを提供するいくつかの gem でサポートされていますか?ご提案いただきありがとうございます。
解決策
方法は 2 つあります。
1 つ目は、呼び出し元に遅延オブジェクトの作成を処理させることです。これは最も単純な解決策であり、Ruby コードでは非常に一般的なパターンです。
class ExpensiveObject
def initialize
# Expensive stuff here.
end
end
class Caller
def some_method
my_object.do_something
end
def my_object
# Expensive object is created when my_object is called. Subsequent calls
# will return the same object.
@my_object ||= ExpensiveObject.new
end
end
2 番目のオプションは、オブジェクト自体を遅延初期化させることです。これを実現するために、実際のオブジェクトの周囲にデリゲート オブジェクトを作成します。このアプローチは少し注意が必要であり、たとえば、変更できない既存の呼び出しコードがある場合を除き、お勧めできません。
class ExpensiveObject # Delegate
class RealExpensiveObject # Actual object
def initialize
# Expensive stuff here.
end
# More methods...
end
def initialize(*args)
@init_args = args
end
def method_missing(method, *args)
# Delegate to expensive object. __object method will create the expensive
# object if necessary.
__object__.send(method, *args)
end
def __object__
@object ||= RealExpensiveObject.new(*@init_args)
end
end
# This will only create the wrapper object (cheap).
obj = ExpensiveObject.new
# Only when the first message is sent will the internal object be initialised.
obj.do_something
stdlib デリゲートを使用してこれを構築することもできます。