Twoje dwie części kodu robią bardzo różne rzeczy. Korzystając z klasy instance_eval, oceniasz blok w kontekście obiektu. Oznacza to, że użycie def definiuje metody na tym obiekcie. Oznacza to również, że wywołanie metody bez odbiornika wewnątrz bloku spowoduje wywołanie go na obiekcie.
Kiedy ustępujesz, podajesz siebie jako argument do bloku, ale ponieważ twój blok nie przyjmuje żadnych argumentów, jest po prostu ignorowany. Więc w tym przypadku oddanie siebie robi to samo, co nie daje niczego. def
zachowuje się tutaj dokładnie tak, jak poza tym blokiem, dając samo siebie nie zmienia tego, na co definiujesz metodę. Co można zrobić, to:
class Foo
def initialize
yield self if block_given?
end
end
x = Foo.new {|obj| def obj.foo() 'foo' end}
x.foo
Różnica do instance_eval jest, że trzeba określić odbiornik wyraźnie.
Edycja wyjaśnienie:
W wersji z wydajnością obj w bloku jest obiekt, który jest uzyskane, która w tym przypadku jest to nowoutworzone przykład foo. Podczas gdy jaźń będzie miała taką samą wartość, jaką miała poza blokiem. Dzięki instancji instance_eval w wersji self
wewnątrz bloku zostanie utworzona nowo utworzona instancja Foo.
W swojej "Edycji do wyjaśnienia", nie masz na myśli, że jaźń uległa obstawieniu w bloku? Być może po prostu czytam to w inny sposób, ale widzę, że obiekt jest inicjowany, self jest poddawany blokowi jako "obj", a następnie wewnątrz bloku metoda foo jest definiowana na self przez obj. – uzo
Jestem prawie pewien, mamy na myśli to samo. Napisałem "nowo utworzoną instancję Foo", ponieważ self wewnątrz metody initialize (która jest nowo utworzoną instancją Foo) nie jest tym samym, co self wewnątrz bloku i jeśli po prostu powiesz "self", nie jest jasne, które masz na myśli. – sepp2k