Is it possible in Ruby to get a reference to methods of an object ( I would like to know if this can be done without procs/lambdas ) , for example , consider the following code :
class X def initialize @map = {} setup_map end private def setup_map # @map["a"] = get reference to a method # @map["b"] = get reference to b method # @map["c"] = get referebce to c method end public def call(a) @map["a"](a) if a > 10 @map["b"](a) if a > 20 @map["c"](a) if a > 30 end def a(arg) puts "a was called with #{arg}" end def b(arg) puts "b was called with #{arg}" end def c(arg) puts "c was called with #{arg}" end end
Is it possible to do such thing ? I would like to avoid procs/lambdas because I want to be able to change the behaviour of A,B,C by subclassing .
Method references are a special type of lambda expressions. They're often used to create simple lambda expressions by referencing existing methods. There are four kinds of method references: Static methods. Instance methods of particular objects. Instance methods of an arbitrary object of a particular type.
Types of Method ReferencesStatic Method Reference. Instance Method Reference of a particular object. Instance Method Reference of an arbitrary object of a particular type. Constructor Reference.
Method reference is used to refer method of functional interface. It is compact and easy form of lambda expression. Each time when you are using lambda expression to just referring a method, you can replace your lambda expression with method reference.
You want Object#method
:
---------------------------------------------------------- Object#method obj.method(sym) => method ------------------------------------------------------------------------ Looks up the named method as a receiver in obj, returning a Method object (or raising NameError). The Method object acts as a closure in obj's object instance, so instance variables and the value of self remain available. class Demo def initialize(n) @iv = n end def hello() "Hello, @iv = #{@iv}" end end k = Demo.new(99) m = k.method(:hello) m.call #=> "Hello, @iv = 99" l = Demo.new('Fred') m = l.method("hello") m.call #=> "Hello, @iv = Fred"
Now your code becomes:
private def setup_map @map = { 'a' => method(:a), 'b' => method(:b), 'c' => method(:c) } # or, more succinctly # @map = Hash.new { |_map,name| _map[name] = method(name.to_sym) } end public def call(arg) @map["a"][arg] if arg > 10 @map["b"][arg] if arg > 20 @map["c"][arg] if arg > 30 end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With