How to use define_method inside initialize()

后端 未结 3 907
名媛妹妹
名媛妹妹 2021-02-01 03:56

Trying to use define_method inside initialize but getting undefined_method define_method. What am I doing wrong?

class C
          


        
相关标签:
3条回答
  • 2021-02-01 04:10

    Do as below :

    class C
      def initialize(n)    
        self.class.send(:define_method,n) { puts "some method #{n}" }    
      end
    end
    
    ob = C.new("abc")
    ob.abc
    # >> some method abc
    

    Module#define_method is a private method and also a class method.Your one didn't work,as you tried to call it on the instance of C.You have to call it on C,using #send in your case.

    0 讨论(0)
  • 2021-02-01 04:23

    I suspect that you're looking for define_singleton_method:

    define_singleton_method(symbol, method) → new_method
    define_singleton_method(symbol) { block } → proc

    Defines a singleton method in the receiver. The method parameter can be a Proc, a Method or an UnboundMethod object. If a block is specified, it is used as the method body.

    If you use define_method on self.class, you'll create the new method as an instance method on the whole class so it will be available as a method on all instances of the class.

    You'd use define_singleton_method like this:

    class C
      def initialize(s)    
        define_singleton_method(s) { puts "some method #{s}" }    
      end
    end
    

    And then:

    a = C.new('a')
    b = C.new('b')
    a.a # puts 'some method a'
    a.b # NoMethodError
    b.a # NoMethodError
    b.b # puts 'some method b'
    

    If your initialize did:

    self.class.send(:define_method,n) { puts "some method #{n}" }    
    

    then you'd get:

    a.a # puts 'some method a'
    a.b # puts 'some method b'
    b.a # puts 'some method a'
    b.b # puts 'some method b'
    

    and that's probably not what you're looking for. Creating a new instance and having the entire class change as a result is rather odd.

    0 讨论(0)
  • 2021-02-01 04:23

    You were almost there. Just point to the class with self.class, don't even need to use :send:

    class C
      def initialize(n)    
        self.class.define_method ("#{n}") { puts "some method #{n}" }    
      end
    end
    ob = C.new('new_method')
    ob2 = C.new('new_method2')
    # Here ob and ob2 will have access to new_method and new_method2 methods
    

    You can also use it with :method_missing to teach your class new methods like this:

    class Apprentice
      def method_missing(new_method)
        puts "I don't know this method... let me learn it :)"
        self.class.define_method(new_method) do
          return "This is a method I already learned from you: #{new_method}"
        end
      end
    end
    ap = Apprentice.new
    ap.read
    => "I don't know this method... let me learn it :)"
    ap.read
    => "This is a method I already learned from you: read"
    
    0 讨论(0)
提交回复
热议问题