क्लास के तरीके बनाने के लिए मैं कैसे define_method का उपयोग करता हूं?


108

यह उपयोगी है यदि आप वर्ग विधि को रूपक रूप से बनाने की कोशिश कर रहे हैं:

def self.create_methods(method_name)
    # To create instance methods:
    define_method method_name do
      ...
    end

    # To create class methods that refer to the args on create_methods:
    ???
end

मेरे जवाब का पालन करें ...

जवाबों:


196

मुझे लगता है कि रूबी 1.9 में आप ऐसा कर सकते हैं:

class A
  define_singleton_method :loudly do |message|
    puts message.upcase
  end
end

A.loudly "my message"

# >> MY MESSAGE

4
भीsingleton_class.define_method
Pyro

@Pyro को स्पष्ट करने के लिए, क्या आप अभी जाएंगे singleton_class.define_method :loudly do |message|आदि?
जोशुआ पिंटर

25

मैं डिस्क्रिप्शन टू कॉल डिफाइन_मिथोड का उपयोग करना पसंद करता हूं, और मुझे मेटाक्लास तक पहुंचने के लिए एक मेटाक्लस विधि बनाना भी पसंद है:

class Object
  def metaclass
    class << self
      self
    end
  end
end

class MyClass
  # Defines MyClass.my_method
  self.metaclass.send(:define_method, :my_method) do
    ...
  end
end

2
धन्यवाद! निश्चित रूप से अपने लिए यह अच्छा बनाने के तरीके हैं। लेकिन अगर आप एक ओपन सोर्स प्लगइन पर काम कर रहे हैं, उदाहरण के लिए, मुझे लगता है कि यह नेमस्पेस को रोकना नहीं है metaclass, इसलिए आसान, स्टैंडअलोन शॉर्टहैंड जानना अच्छा है।
चिनसौर

मैंने अपने मूल उत्तर के साथ जाने का फैसला किया। मेरी समझ यह है कि रूबी 1.9 में चले जाने पर निजी तरीकों को एक्सेस करने के लिए सेंड () का उपयोग करना, ताकि उपयोग करने के लिए अच्छी बात न लगे। इसके अलावा अगर आप एक से अधिक तरीकों को परिभाषित कर रहे हैं, उदाहरण के लिए एक ब्लॉक क्लीनर है।
चिनसौर

@ विंसेंट रॉबर्ट कोई लिंक जो मेटाक्लस विधि के जादू की व्याख्या करेगा?
अमोल पुजारी

वर्ग << स्व; स्वयं; समाप्त; बस स्व (वर्ग << स्व) के वर्ग को फिर से खोल देता है और फिर उस वर्ग (स्व) को वापस लौटाता है ताकि वास्तव में स्वयं की मेटाक्लस वापस आ जाए।
विंसेंट रॉबर्ट

10

रूबी 1.8+ में यह सबसे सरल तरीका है:

class A
  class << self
    def method_name
      ...
    end
  end
end

1
मुझे यह वास्तव में पसंद है। छोटा, साफ, अच्छी तरह से पढ़ता है और यह पोर्टेबल है। बेशक, आप पूछ सकते हैं कि मैं 2013 में रूबी 1.8 का उपयोग कर रहा हूं ...
ए फादर डार्कली

8

से व्युत्पन्न: जे और क्यों , जो इस प्रिटियर को बनाने के तरीके भी प्रदान करते हैं।

self.create_class_method(method_name)
  (class << self; self; end).instance_eval do
    define_method method_name do
      ...
    end
  end
end

अद्यतन : नीचे वीआर के योगदान से; एक अधिक संक्षिप्त विधि (जब तक आप केवल एक विधि को इस तरह परिभाषित कर रहे हैं) जो अभी भी स्टैंडअलोन है:

self.create_class_method(method_name)
  (class << self; self; end).send(:define_method, method_name) do
    ...
  end
end

लेकिन ध्यान दें कि डिफरेंशियल मेथड्स जैसे डिफेंस_मिथोड () एक्सेस करने के लिए सेंड () का उपयोग करना जरूरी नहीं है कि यह एक अच्छा आइडिया है (मेरी समझ से यह रूबी 1.9 में दूर हो रहा है)।


बेहतर (?) विकल्प हो सकता है कि चीजों को एक मॉड्यूल में रखा जाए और फिर अपने create_class_method को वर्ग पर मॉड्यूल का विस्तार किया जाए ??? देखें: blog.jayfields.com/2008/07/ruby-underuse-of-modules.html
चिनसौर

6

रेल में इस्तेमाल किया जा सकता है अगर आप चिंता से गतिशील रूप से वर्ग विधियों को परिभाषित करना चाहते हैं:

module Concerns::Testable
  extend ActiveSupport::Concern

  included do 
    singleton_class.instance_eval do
      define_method(:test) do
        puts 'test'
      end
    end
  end
end

-1

आप कुछ इस तरह से भी कर सकते हैं बिना डिफेंड_मिथोड पर निर्भर हुए:

A.class_eval do
  def self.class_method_name(param)
    puts param
  end
end

A.class_method_name("hello") # outputs "hello" and returns nil
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.