रूबी में निजी मॉड्यूल के तरीके


108

मेरा एक दो हिस्सा है

सर्वश्रेष्ठ प्रणालियां

  • मेरे पास एक एल्गोरिथ्म है जो सार्वजनिक इंटरफ़ेस का उपयोग करके डेटा संरचना पर कुछ ऑपरेशन करता है
  • यह वर्तमान में एक सार्वजनिक इंटरफ़ेस विधि को छोड़कर, सभी कई स्थिर विधियों के साथ एक मॉड्यूल है।
  • एक उदाहरण चर है जिसे सभी तरीकों के बीच साझा करने की आवश्यकता है।

ये वे विकल्प हैं जो मैं देख सकता हूं, जो सबसे अच्छा है ?:

  • मॉड्यूल स्थिर (माणिक में 'मॉड्यूल') के साथ तरीकों
  • स्थिर विधियों के साथ कक्षा
  • डेटा संरचना में शामिल करने के लिए मिक्सिन मॉड्यूल
  • उस डेटा संरचना को संशोधित करने वाले एल्गोरिथम के भाग को रिफलेक्टर करता है (बहुत छोटा) और ऐसा मिश्रण बनाता है जो एल्गोरिथम मॉड्यूल के स्थिर तरीकों को कॉल करता है

तकनीकी हिस्सा है

क्या एक निजी मॉड्यूल विधि बनाने का कोई तरीका है ?

module Thing
  def self.pub; puts "Public method"; end
  private
  def self.priv; puts "Private method"; end
end

privateवहाँ में कोई असर दिखाई नहीं देता मैं अभी भी कॉल कर सकते हैं, Thing.privइस मुद्दे के बिना।


5
FYI करें रूबी में 'स्टैटिक' पद्धति जैसी कोई चीज नहीं है, उन्हें क्लास इंस्टेंस मेथड्स कहा जाता है
brad

31
एक पुरानी टिप्पणी है, लेकिन जैसा कि चार upvotes है, मुझे यह बताना चाहिए कि 'क्लास इंस्टेंस विधि' जैसी कोई चीज नहीं है। Method क्लास मेथड ’सही शब्द है।
micapam

5
privateकेवल उदाहरण के तरीकों को प्रभावित करता है, वर्ग के तरीकों को नहीं। private_class_methodइसके बजाय का उपयोग करें :module Thing; def self.pub; end; private_class_method :pub; end
apeiros

1
@micapam कक्षा उदाहरण विधियाँ रूबी में मौजूद हैं, और वे कक्षा विधियों से भिन्न हैं।
मार्नेन लाइबो-कोसर

जवाबों:


88

मुझे लगता है कि ऐसा करने के लिए सबसे अच्छा तरीका (और ज्यादातर मौजूदा काम कैसे लिखा जाता है) ऐसा करने के लिए मॉड्यूल के भीतर एक वर्ग बनाकर सभी तर्क से संबंधित है, और मॉड्यूल सिर्फ एक सुविधाजनक तरीका प्रदान करता है, जैसे।

module GTranslate
  class Translator
    def perform( text ); translate( text ); end

    private

    def translate( text )
      # do some private stuff here
    end
  end

  def self.translate( text )
    t = Translator.new
    t.perform( text )
  end
end

14
रूबी newb यहाँ। इस उदाहरण में, क्या ट्रांसलेटर वर्ग को मॉड्यूल के सार्वजनिक इंटरफ़ेस के हिस्से के रूप में उजागर किया गया है? क्या 'प्रदर्शन' विधि इसकी पहुंच GTranslate तक सीमित है?
rshepherd

2
@rshepherd performवह विधि नहीं है जिसे यहाँ निजी माना जाता है, निजी विधि Translatorकक्षा में निजी पद्धति है (@ ucron के उदाहरण में कोई नहीं है, जो बहुत दुर्भाग्यपूर्ण है)। GTranslate.translateके लिए केवल एक सुविधाजनक तरीका है GTranslate::Translator#perform, इसे छुपाने का कोई वास्तविक लाभ नहीं है, अगर यह संभव था।
माईकेलpm

28
मुझे यकीन नहीं है कि यहाँ एक वर्ग होने से क्या हासिल होता है। यदि लक्ष्य एक निजी मॉड्यूल विधि है, तो यह लक्ष्य पूरा नहीं करता है। क्योंकि आप GTranslate :: Translator.new.perform पर कॉल करके मॉड्यूल के बाहर से "प्रदर्शन" विधि का उपयोग कर सकते हैं। अन्य पासवर्ड में, यह निजी नहीं है।
ज़ैक जू

1
@jschorr मुझे लगता है कि Op और यह उत्तर एक निजी वर्ग या मॉड्यूल विधि बनाने का इरादा रखता है, न कि एक उदाहरण विधि। इसके अलावा, यह किसी भी उदाहरण विधि को निजी नहीं self.translateबनायेगा क्योंकि एक वर्ग / मॉड्यूल विधि घोषित करता है।
konsolebox

5
GTranslate::Translator.new.perform(text)- दृढ़, लेकिन निजी नहीं!
abhillman

80

वहाँ भी है Module.private_class_method, जो यकीनन अधिक आशय व्यक्त करता है।

module Foo
  def self.included(base)
    base.instance_eval do
      def method_name
        # ...
      end
      private_class_method :method_name
    end
  end
end

प्रश्न में कोड के लिए:

module Thing
  def self.pub; puts "Public method"; end
  def self.priv; puts "Private method"; end
  private_class_method :priv
end

रूबी 2.1 या नया:

module Thing
  def self.pub; puts "Public method"; end
  private_class_method def self.priv; puts "Private method"; end
end

मुझे इसकी जानकारी नहीं थी। क्या यह विधि की परिभाषा से पहले भी काम करेगा, जैसे private?
मार्नेन लाइबो-कोसर

7
@ JCooper के उत्तर के साथ यह उत्तर वास्तविक समाधान है। @ MarnenLaibow-Koser यह नहीं है। आप अधिक समूह और इंडेंटेशन की कीमत पर अन्य उत्तर पर विचार कर सकते हैं। यह वास्तव में कुछ के लिए पसंदीदा समाधान हो सकता है। (केवल संदर्भ के लिए जवाब दे रहा है।)
konsolebox

58
module Writer
  class << self
    def output(s)
      puts upcase(s)
    end

    private

    def upcase(s)
      s.upcase
    end
  end
end

Writer.output "Hello World"
# -> HELLO WORLD

Writer.upcase "Hello World"
# -> so.rb:16:in `<main>': private method `upcase' called for Writer:Module (NoMethodError)

4
यह स्वीकृत उत्तर होना चाहिए। मेरी राय में स्वच्छ और मुहावरेदार।
मार्टिन न्यागा

@MartinNyaga में include Writerविकल्प न होने का दोष है !
उलसीसे बीएन

28

एक मॉड्यूल में मिलाए जाने पर आप फैंसी चीजों को करने के लिए "शामिल" विधि का उपयोग कर सकते हैं। यह आपके विचार के अनुसार करता है:

module Foo
  def self.included(base)
    class << base 
      def public_method
        puts "public method"
      end
      def call_private
        private_method
      end
      private
      def private_method
        puts "private"
      end
    end
  end
end

class Bar
  include Foo
end

Bar.public_method

begin
  Bar.private_method
rescue
  puts "couldn't call private method"
end

Bar.call_private

5
यह चालाकी है। तो यह संभव है, लेकिन शायद इसके लायक नहीं है।
डैनियल बर्ड्सले

अच्छा काम करता है। मैंने included do |base| [...] end
डिफ के

5
@ क्रिस्टल: सिंटैक्स केवल ऐसे मॉड्यूल्स पर मौजूद होता है जो ActiveSupport का विस्तार करते हैं :: यदि मैं गलत नहीं हूं तो चिंता करें। यानी यह एक रेल की बात है।
वाज

11

दुर्भाग्य से, privateकेवल उदाहरण के तरीकों पर लागू होता है। कक्षा में निजी "स्थिर" तरीके प्राप्त करने का सामान्य तरीका कुछ ऐसा करना है:

class << self
  private

  def foo()
   ....
  end
end

बेशक मैं मॉड्यूल में ऐसा करने के साथ नहीं खेला है।


7
यह सच नहीं है। आपके पास निजी वर्ग विधियाँ और निजी मॉड्यूल विधियाँ हो सकती हैं।
mikeycgto

आपके पास निजी कक्षा विधियां हो सकती हैं, लेकिन ऐसा करने से .fooनिजी कक्षा विधि नहीं बनेगी: "निजी; डीएफ़ सेल्फ.फू ()"
अरी

निजी वर्ग विधियों और निजी मॉड्यूल विधियों के बीच अंतर को विस्तृत करने के लिए @mikeycgto केयर? क्योंकि मुझे लगता है कि वे सिर्फ एक ही हैं। ध्यान दें कि दोनों privateऔर private_class_methodस्वामित्व में Moduleहैं Class। यह कोड वैसे काम करता है और यह उपयोग करने का विकल्प है private_class_method
konsolebox

3

एक अच्छा तरीका इस तरह है

module MyModule
  class << self
    def public_method
      # you may call the private method here
      tmp = private_method
      :public
    end

    private def private_method
      :private
    end
  end
end

# calling from outside the module
puts MyModule::public_method

1

कक्षा चर / स्थिरांक के भीतर लंबोदर के रूप में भंडारण विधियों के बारे में क्या है?

module MyModule
  @@my_secret_method = lambda {
    # ...
  }
  # ...
end

परीक्षण के लिए:
यूपीडी: 6 साल बाद इस कोड का भारी अपडेट निजी विधि घोषित करने के लिए क्लीनर तरीका दिखाता हैd

module A
  @@L = lambda{ "@@L" }
  def self.a ; @@L[] ; end
  def self.b ; a ; end

  class << self
    def c ; @@L[] ; end
    private
    def d ; @@L[] ; end
  end
  def self.e ; c ; end
  def self.f ; self.c ; end
  def self.g ; d ; end
  def self.h ; self.d ; end

  private
  def self.i ; @@L[] ; end
  class << self
    def j ; @@L[] ; end
  end

  public
  def self.k ; i ; end
  def self.l ; self.i ; end
  def self.m ; j ; end
  def self.n ; self.j ; end
end

for expr in %w{ A.a A.b A.c A.d A.e A.f A.g A.h A.i A.j A.k A.l A.m A.n }
  puts "#{expr} => #{begin ; eval expr ; rescue => e ; e ; end}"
end

यहाँ हम देखते हैं कि:

A.a => @@L
A.b => @@L
A.c => @@L
A.d => private method `d' called for A:Module
A.e => @@L
A.f => @@L
A.g => @@L
A.h => private method `d' called for A:Module
A.i => @@L
A.j => @@L
A.k => @@L
A.l => @@L
A.m => @@L
A.n => @@L

1) @@Lबाहर से एक्सेस नहीं किया जा सकता है, लेकिन लगभग हर जगह से पहुंच योग्य है
2) class << self ; private ; defसफलतापूर्वक dबाहर से और अंदर से दुर्गम विधि को बनाता है self.लेकिन इसके बिना नहीं - यह अजीब है
3) private ; self.और private ; class << selfतरीकों को निजी न बनाएं - वे दोनों सुलभ हैं साथ और बिना साथself.


lambdas तरीकों के रूप में एक ही चीज में नहीं हैं। लैम्ब्डा टाइप के होते हैं Proc, जबकि तरीके टाइप के होते हैं Method
माइकल डोरस्ट

1
वैश्विक चर ख़राब हैं
शेमपियन

@achempion, आप उन्हें कहाँ देखते हैं?
नैकिलोन

@ नाकिलोन मेरी माफी, अगर आप चाहते हैं कि मैं अपना वोट रद्द कर दूं तो अपना जवाब संपादित करें
il

0

एक निजी मॉड्यूल या कक्षा बनाएं

स्थिरांक कभी भी निजी नहीं होते हैं। हालाँकि, किसी मॉड्यूल या वर्ग को बिना किसी नियत के बनाए बनाना संभव है।

तो इसका एक विकल्प :private_class_methodनिजी मॉड्यूल या वर्ग बनाना और उस पर सार्वजनिक तरीकों को परिभाषित करना है।

module PublicModule
  def self.do_stuff(input)
    @private_implementation.do_stuff(input)
  end

  @private_implementation = Module.new do
    def self.do_stuff(input)
      input.upcase # or call other methods on module
    end
  end
end

उपयोग:

PublicModule.do_stuff("whatever") # => "WHATEVER"

मॉड्यूल के लिए डॉक्स देखें । नया और Class.new


मुझे वास्तव में यह तरीका पसंद है। लेकिन यह .selfविधि परिभाषाओं को हटाने के लिए संभव नहीं है , इसे किसी अन्य वर्ग में शामिल करें, और उन्हें शामिल वर्ग के उदाहरण_मिथोड्स के रूप में उपयोग करें। क्या आपको पता है कि इसे बनाने का कोई तरीका है?
शियासन

0

यह विधि निजी विधियों के साथ डेटा साझा करने की अनुमति नहीं देगी जब तक कि आप स्पष्ट रूप से विधि मापदंडों द्वारा डेटा पास नहीं करते हैं।

module Thing
  extend self

  def pub
    puts priv(123)
  end

  private
  
  def priv(value)
    puts "Private method with value #{value}"
  end
end

Thing.pub
# "Private method with value 123"

Thing.priv
# NoMethodError (private method `priv' called for Thing:Module)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.