Vorrei sostituire l'implementazione di un metodo per un oggetto con un blocco specificato dall'utente. In JavaScript, questo è facilmente realizzabile:Sostituire dinamicamente l'implementazione del metodo su un oggetto in Ruby
function Foo() {
this.bar = function(x) { console.log(x) }
}
foo = new Foo()
foo.bar("baz")
foo.bar = function(x) { console.error(x) }
foo.bar("baz")
In C# è anche abbastanza facile
class Foo
{
public Action<string> Bar { get; set; }
public Foo()
{
Bar = x => Console.WriteLine(x);
}
}
var foo = Foo.new();
foo.Bar("baz");
foo.Bar = x => Console.Error.WriteLine(x);
foo.Bar("baz");
Ma come posso fare la stessa cosa in Ruby? Ho una soluzione che memorizza una lambda in una variabile di istanza ed il metodo chiama il lambda, ma non mi piace molto il sovraccarico e la sintassi
class Foo
def initialize
@bar = lambda {|x| puts x}
end
def bar x
@bar.call x
end
def bar= blk
@bar = blk
end
end
foo = Foo.new
foo.bar "baz"
foo.bar= lambda {|x| puts "*" + x.to_s}
foo.bar "baz"
Mi piacerebbe avere una sintassi del genere:
foo.bar do |x|
puts "*" + x.to_s
end
foo.bar "baz"
mi si avvicinò con il seguente codice
class Foo
def bar x = nil, &blk
if (block_given?)
@bar = blk
elsif (@bar.nil?)
puts x
else
@bar.call x
end
end
end
Ma questo è un pò brutto per più di un parametro e ancora non si sente 'giusto'. Potrei anche definire un metodo set_bar, ma non mi piace neanche :).
class Foo
def bar x
if (@bar.nil?)
puts x
else
@bar.call x
end
end
def set_bar &blk
@bar = blk
end
end
Quindi domanda è: C'è un modo migliore fare per fare questo e se no, quale modo si preferisce
Edit: @ approccio di welldan97 funziona, ma ho sciolto la portata variabile locale, vale a dire
prefix = "*"
def foo.bar x
puts prefix + x.to_s
end
non funziona. Suppongo che devo restare con lambda perché funzioni?
oh beh, probabilmente era troppo facile \ * facepalm \ * :) – kev
hmm, perdo l'ambito su variabili locali, ad esempio 'prefix =" * "; def foo.bar x; inserisce prefisso + x.to_s; fine' non funziona:/ – kev
@ welldan97, come posso sostituire il metodo "setter" per un oggetto specifico? – gaussblurinc