2008-08-21 15 views
14

बेशक self.class.send :method, args... के अलावा। मैं कोड को डुप्लिकेट किए बिना कक्षा और आवृत्ति स्तर दोनों में एक जटिल विधि उपलब्ध करना चाहता हूं।रूबी में एक उदाहरण से एक निजी कक्षा विधि को कॉल करने का कोई तरीका है?


अद्यतन:

@Jonathan Branam: कि मेरी धारणा थी, लेकिन मुझे यकीन है कि और कोई नहीं के चारों ओर एक रास्ता मिल गया था बनाना चाहते थे। रुबी में दृश्यता जावा से बहुत अलग है।

class Foo 
    class <<self 
    private 
    def bar 
     puts 'bar' 
    end 
    end 
end 

Foo.bar 
# => NoMethodError: private method 'bar' called for Foo:Class 

उत्तर

11

यहाँ सवाल के साथ साथ जाने के लिए एक कोड का टुकड़ा है। कक्षा परिभाषा में "निजी" का उपयोग कक्षा विधियों पर लागू नहीं होता है। आपको निम्नलिखित उदाहरणों में "private_class_method" का उपयोग करने की आवश्यकता है।

class Foo 
    def self.private_bar 
    # Complex logic goes here 
    puts "hi" 
    end 
    private_class_method :private_bar 
    class <<self 
    private 
    def another_private_bar 
     puts "bar" 
    end 
    end 
    public 
    def instance_bar 
    self.class.private_bar 
    end 
    def instance_bar2 
    self.class.another_private_bar 
    end 
end 

f=Foo.new 
f=instance_bar # NoMethodError: private method `private_bar' called for Foo:Class 
f=instance_bar2 # NoMethodError: private method `another_private_bar' called for Foo:Class 

मुझे इस के आसपास जाने का कोई तरीका नहीं दिख रहा है। दस्तावेज़ीकरण कहता है कि आप एक निजी विधि प्राप्त नहीं कर सकते हैं। इसके अलावा आप एक ही उदाहरण से केवल एक निजी विधि तक पहुंच सकते हैं। कक्षा फू फू के दिए गए उदाहरण की तुलना में एक अलग वस्तु है।

मेरा उत्तर अंतिम के रूप में न लें। मैं निश्चित रूप से एक विशेषज्ञ नहीं हूं, लेकिन मैं एक कोड स्निपेट प्रदान करना चाहता था ताकि अन्य जो उत्तर देने का प्रयास करेंगे, वे उचित रूप से निजी वर्ग के तरीके होंगे।

-1

जब तक मैं गलतफहमी हूँ, तुम सिर्फ कुछ इस तरह की जरूरत नहीं है:

तुम भी बहुत सही है कि private वर्ग के तरीकों पर काम नहीं करता है, हालांकि यह एक निजी वर्ग प्रणाली की घोषणा करेगा
class Foo 
    private 
    def Foo.bar 
     # Complex logic goes here 
     puts "hi" 
    end 

    public 
    def bar 
     Foo.bar 
    end 
end 

बेशक आप अगर तुम वर्ग के नाम हार्डकोड से बचना चाहते थे अपने self.class.send दृष्टिकोण का उपयोग करने दूसरी परिभाषा को बदल सकता है ...

0

अपने विधि केवल है एक utility function (जो है, यह किसी भी उदाहरण चर पर निर्भर नहीं करता), तो आपको इतना है कि यह दोनों एक निजी वर्ग पद्धति के रूप में उपलब्ध है विधि एक मॉड्यूल और include और extend में वर्ग डाल सकता है और एक निजी उदाहरण विधि।

0

यह "वास्तविक" निजी वर्ग विधियों के साथ खेलने का तरीका है।

class Foo 
    def self.private_bar 
    # Complex logic goes here 
    puts "hi" 
    end 
    private_class_method :private_bar 
    class <<self 
    private 
    def another_private_bar 
     puts "bar" 
    end 
    end 
    public 
    def instance_bar 
    self.class.private_bar 
    end 
    def instance_bar2 
    self.class.another_private_bar 
    end 
    def calling_private_method 
    Foo.send :another_private_bar 
    self.class.send :private_bar 
    end 
end 
f=Foo.new 
f.send :calling_private_method 
# "bar" 
# "hi" 
Foo.send :another_private_bar 
# "bar" 

चियर्स

+0

पहले उदाहरण के लिए त्रुटि प्राप्त करना: '1.9।3p327: 078> f = Foo.new => # <फू: 0x0000000293baa0> 1.9.3p327: 079> f.class.send: calling_private_method NoMethodError: अपरिभाषित विधि \ 'calling_private_method 'फू के लिए: कक्षा से (आईआरबी) : 79 ~/.rvm/rubies/ruby-1.9.3-p327/bin/irb: 16: \ '

'' – TrinitronX

+0

हाँ, यह काम नहीं करता है (या शायद अब काम नहीं करता है)। –

+0

एक टाइपो - मेरे कोड @JacobCrofts – metakungfu

3

मुझे अधिक या कम अजीब समाधान और गैर समाधान की इस सूची के लिए योगदान करते हैं:

puts RUBY_VERSION # => 2.1.2 

class C 
    class << self 
    private def foo 
     'Je suis foo' 
    end 
    end 

    private define_method :foo, &method(:foo) 

    def bar 
    foo 
    end 
end 

puts C.new.bar # => Je suis foo 
puts C.new.foo # => NoMethodError 
+1

मूल पोस्ट अनुरोध के रूप में, इसे * क्लास विधि * कॉल करना चाहिए। यह अच्छा नहीं है क्योंकि यह विधि के उदाहरण विधियों के सेट में विधि की प्रतिलिपि बना रहा है। यदि आप, उदाहरण के लिए, बंदर क्लास विधि सी :: foo पैच करता है, तो आप अचानक कक्षा स्तर :: foo और instance level #foo के बीच मेल नहीं खाते हैं। –

+0

मुझे लगता है कि आप सही हैं, धन्यवाद। – Alexey

0

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

class MyClass 

    private_class_method def self.my_private_method 
    puts "private class method" 
    end 

    private def my_private_method 
    puts "private instance method" 
    end 

end 

और नहीं, तुम एक उदाहरण विधि से एक निजी वर्ग विधि कॉल नहीं कर सकते। हालांकि, अगर आप के बजाय निजी वर्ग सार्वजनिक वर्ग पद्धति के रूप में एक निजी नेस्टेड कक्षा में विधि के बजाय लागू कर सकता है, private_constant सहायक विधि का उपयोग कर। अधिक जानकारी के लिए this blogpost देखें।

संबंधित मुद्दे