Rubyの場合、オブジェクトの作成が必要になる可能性がありますが、よくわかりません。また、オブジェクトの作成にはコストがかかる可能性があるため、私はオブジェクトの作成にあまり熱心ではありません。これは遅延読み込みの明確なケースだと思います。誰かがメッセージを送信したときにのみ作成されないオブジェクトを定義するにはどうすればよいですか?オブジェクトはブロック内に作成されます。Rubyで単純な遅延読み込み/初期化を行う方法はありますか?これらのものは、オブジェクトの遅延初期化のさまざまなケースに異なるソリューションを提供するいくつかの宝石によってサポートされていますか?あなたの提案をありがとう!
20299 次
2 に答える
40
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
stdlibdelegate
を使用して、これを上に構築することもできます。
于 2010-03-17T10:51:46.767 に答える
7
コードの断片を遅延評価したい場合は、プロキシを使用します。
class LazyProxy
# blank slate... (use BasicObject in Ruby 1.9)
instance_methods.each do |method|
undef_method(method) unless method =~ /^__/
end
def initialize(&lazy_proxy_block)
@lazy_proxy_block = lazy_proxy_block
end
def method_missing(method, *args, &block)
@lazy_proxy_obj ||= @lazy_proxy_block.call # evaluate the real receiver
@lazy_proxy_obj.send(method, *args, &block) # delegate unknown methods to the real receiver
end
end
次に、次のように使用します。
expensive_object = LazyProxy.new { ExpensiveObject.new }
expensive_object.do_something
このコードを使用して、高価なものの任意の複雑な初期化を行うことができます。
expensive_object = LazyProxy.new do
expensive_helper = ExpensiveHelper.new
do_really_expensive_stuff_with(expensive_helper)
ExpensiveObject.new(:using => expensive_helper)
end
expensive_object.do_something
それはどのように機能しますか?Proc で高価なオブジェクトを構築する方法についての指示を保持する LazyProxy オブジェクトをインスタンス化します。その後、プロキシ オブジェクトで何らかのメソッドを呼び出すと、最初に高価なオブジェクトがインスタンス化され、次にメソッド呼び出しが委任されます。
于 2010-03-17T13:50:06.087 に答える