Ruby Language
Metaprogramming
खोज…
परिचय
मेटाप्रोग्रामिंग को दो तरीकों से वर्णित किया जा सकता है:
"कंप्यूटर प्रोग्राम जो अन्य प्रोग्राम (या स्वयं) को अपने डेटा के रूप में लिखते हैं या उनमें हेरफेर करते हैं, या जो संकलन समय पर काम करते हैं, जो अन्यथा रनटाइम पर किया जाएगा"।
अधिक सीधे शब्दों में कहें: मेटाप्रोग्रामिंग कोड लिख रहा है जो आपके जीवन को आसान बनाने के लिए रनटाइम के दौरान कोड लिखता है ।
उदाहरण मूल्यांकन का उपयोग करके "के साथ" को लागू करना
कई भाषाओं में एक बयान के with
सुविधा होती है जो प्रोग्रामर को विधि कॉल के रिसीवर को छोड़ देने की अनुमति देता है।
with
आसानी से उपयोग कर रहा रूबी में नकल करते जा सकती है instance_eval
:
def with(object, &block)
object.instance_eval &block
end
with
विधि मूल वस्तुओं पर तरीकों पर अमल करने के लिए इस्तेमाल किया जा सकता है:
hash = Hash.new
with hash do
store :key, :value
has_key? :key # => true
values # => [:value]
end
तरीकों को गतिशील रूप से परिभाषित करना
रूबी के साथ आप निष्पादन समय में कार्यक्रम की संरचना को संशोधित कर सकते हैं। इसे करने का एक तरीका है, विधि method_missing
का उपयोग करके विधियों को परिभाषित करना।
मान लीजिए कि हम यह जांचना चाहते हैं कि कोई संख्या वाक्यविन्यास 777.is_greater_than_123?
साथ अन्य संख्या से अधिक है 777.is_greater_than_123?
।
# open Numeric class
class Numeric
# override `method_missing`
def method_missing(method_name,*args)
# test if the method_name matches the syntax we want
if method_name.to_s.match /^is_greater_than_(\d+)\?$/
# capture the number in the method_name
the_other_number = $1.to_i
# return whether the number is greater than the other number or not
self > the_other_number
else
# if the method_name doesn't match what we want, let the previous definition of `method_missing` handle it
super
end
end
end
एक महत्वपूर्ण बात यह याद रखें कि method_missing
का उपयोग करते समय किसी को respond_to?
ओवरराइड करना चाहिए respond_to?
तरीका:
class Numeric
def respond_to?(method_name, include_all = false)
method_name.to_s.match(/^is_greater_than_(\d+)\?$/) || super
end
end
ऐसा करने के लिए भूल जाने से असंगत स्थिति पैदा होती है, जब आप सफलतापूर्वक 600.is_greater_than_123
कॉल कर सकते हैं, लेकिन 600.respond_to(:is_greater_than_123)
गलत है।
उदाहरणों पर तरीकों को परिभाषित करना
माणिक में आप किसी भी वर्ग के मौजूदा उदाहरणों में विधियाँ जोड़ सकते हैं। यह आपको उस वर्ग के बाकी उदाहरणों के व्यवहार को बदलने के बिना किसी वर्ग के व्यवहार और उदाहरण को जोड़ने की अनुमति देता है।
class Example
def method1(foo)
puts foo
end
end
#defines method2 on object exp
exp = Example.new
exp.define_method(:method2) {puts "Method2"}
#with method parameters
exp.define_method(:method3) {|name| puts name}
भेजना () विधि
send()
का उपयोग object
संदेश send()
लिए किया जाता है। send()
Object
क्लास का एक इंस्टेंस तरीका है। send()
में पहला तर्क send()
संदेश है कि आप वस्तु को भेज रहे हैं - वह है, एक विधि का नाम। यह string
या symbol
हो सकता है लेकिन प्रतीकों को प्राथमिकता दी जाती है। फिर उन तर्कों को विधि में पारित करने की आवश्यकता है, वे शेष तर्क send()
।
class Hello
def hello(*args)
puts 'Hello ' + args.join(' ')
end
end
h = Hello.new
h.send :hello, 'gentle', 'readers' #=> "Hello gentle readers"
# h.send(:hello, 'gentle', 'readers') #=> Here :hello is method and rest are the arguments to method.
यहाँ अधिक वर्णनात्मक उदाहरण है
class Account
attr_accessor :name, :email, :notes, :address
def assign_values(values)
values.each_key do |k, v|
# How send method would look a like
# self.name = value[k]
self.send("#{k}=", values[k])
end
end
end
user_info = {
name: 'Matt',
email: '[email protected]',
address: '132 random st.',
notes: "annoying customer"
}
account = Account.new
If attributes gets increase then we would messup the code
#--------- Bad way --------------
account.name = user_info[:name]
account.address = user_info[:address]
account.email = user_info[:email]
account.notes = user_info[:notes]
# --------- Meta Programing way --------------
account.assign_values(user_info) # With single line we can assign n number of attributes
puts account.inspect
नोट: send()
स्वयं अनुशंसित नहीं है। __send__()
उपयोग करें जिसमें निजी तरीकों को कॉल करने की शक्ति है, या (अनुशंसित) public_send()