Is there a difference between
x = Class.new( or method)
x.method
and开发者_高级运维
Class.new(or method) do |x|
x.method
end
x = SomeClass.new
x.some_method
This first creates an instance of SomeClass
(calling initialize
with no arguments). It then calls the method some_method
on that instance.
SomeClass.new do |x|
x.some_method
end
This creates an instance of SomeClass
, calling initialize
with a block as its argument. That block takes one argument and calls some_method
on that argument. Whether and how often the block will be called and what the argument will be depends entirely on what SomeClass
's initialize method does.
In many cases the pattern
SomeClass.some_creation_method do |x|
x.some_method
end
is used, so that some_creation_method
creates a SomeClass
instance, yields it to the block and then frees all the resources used by that instance after the block finishes (e.g. it could close file handles, delete temporary files etc.). This is what File.open
does.
In the case where the class in question is literally Class
the block will be class_eval
ed on the newly created class, i.e.
c = Class.new do
some_code
end
is equivalent to
c = Class.new
c.class_eval do
some_code
end
Depends on the class. e.g. for File
objects,
File.open("foo.txt", "wb") do |f|
f.write("x")
end
the file handle will be closed automatically when the block exits. But that's only the idiom, in general the class defines the semantics, and chooses if it supplies the variant with the block.
Here is a simple example showing that the two are not equivalent. They would only be equivalent if the initialize
method of your class called yield(self)
at the end.
class MyClass
def initialize( name )
@name = name
end
def say_hi
puts "Hi, I am #{@name}"
end
end
x = MyClass.new( "Bob" )
x.say_hi
#=> Hi, I am Bob
MyClass.new( "Jim" ) do |x|
x.say_hi
end
#=> (nothing prints out)
In the second example, I pass a block to new
, but since my initialize
method doesn't do anything with the block, the contents of the block are never run.
精彩评论