রুবিতে ব্যক্তিগত মডিউল পদ্ধতি


108

আমার একটি দুটি অংশের প্রশ্ন আছে

ভাল অভ্যাস

  • আমার কাছে একটি অ্যালগরিদম আছে যা পাবলিক ইন্টারফেস ব্যবহার করে কোনও ডেটা স্ট্রাকচারে কিছু অপারেশন করে
  • এটি বর্তমানে একটি স্থিতিশীল পদ্ধতি সহ একটি মডিউল যা একটি পাবলিক ইন্টারফেস পদ্ধতি ব্যতীত সমস্ত ব্যক্তিগত।
  • একটি পদ্ধতির পরিবর্তনশীল রয়েছে যা সমস্ত পদ্ধতির মধ্যে ভাগ করে নেওয়া দরকার।

এই বিকল্পগুলি আমি দেখতে পাচ্ছি, কোনটি সেরা ?:

  • মডিউল স্ট্যাটিক (রুবি এ 'মডিউল') দিয়ে পদ্ধতি
  • স্থির পদ্ধতি সহ ক্লাস
  • ডেটা স্ট্রাকচারের অন্তর্ভুক্তির জন্য মিক্সিন মডিউল
  • অ্যালগরিদমের সেই অংশটি রিফ্যাক্টর যা ডাটা স্ট্রাকচারকে (খুব ছোট) পরিবর্তন করে এবং এমন একটি মিক্সিন তৈরি করে যা অ্যালগরিদম মডিউলের স্থির পদ্ধতিগুলিকে ডাকে

প্রযুক্তিগত অংশ

একটি ব্যক্তিগত মডিউল পদ্ধতি তৈরি করার কোনও উপায় আছে ?

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

privateসেখানে কোনো প্রভাব বলে মনে হচ্ছে না আমি এখনও কল করবো Thing.privইস্যু ছাড়াই।


5
এফওয়াইআই রুবিতে 'স্ট্যাটিক' পদ্ধতি বলে কিছুই নেই, তাদের শ্রেণি উদাহরণ পদ্ধতি বলা হয়
ব্র্যাড

31
একটি পুরানো মন্তব্য, তবে এটির চারটি উর্ধ্বগতি রয়েছে বলে আমার অবশ্যই উল্লেখ করতে হবে যে 'শ্রেণির উদাহরণ পদ্ধতি' এর মতো কোনও জিনিস নেই। 'শ্রেণি পদ্ধতি' সঠিক শব্দ।
মাইপাপাম

5
privateশ্রেণীর পদ্ধতিগুলিতে নয় কেবল উদাহরণের পদ্ধতিগুলিকেই প্রভাবিত করে। private_class_methodপরিবর্তে ব্যবহার করুন:module Thing; def self.pub; end; private_class_method :pub; end
এপিওরোস

1
@ এমকিপ্যাম ক্লাস উদাহরণ পদ্ধতিগুলি রুবিতে বিদ্যমান এবং সেগুলি ক্লাস পদ্ধতি থেকে পৃথক।
মার্নেন লাইবো-কোসার 14

উত্তর:


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
রুবি এখানে নতুন। এই উদাহরণস্বরূপ, অনুবাদক শ্রেণিটি মডিউলটির সার্বজনীন ইন্টারফেসের অংশ হিসাবে উন্মুক্ত? 'পারফর্ম' পদ্ধতিতে এর অ্যাক্সেসটি জি ট্রান্সলেট এ সীমাবদ্ধ থাকতে পারে?
শেফার্ড

2
@ আর শেফার্ড এই performপদ্ধতিটি এখানে ব্যক্তিগত বলে মনে করা হয় না, ব্যক্তিগত পদ্ধতিটি Translatorশ্রেণীর ব্যক্তিগত পদ্ধতি (@ ইউক্রনের উদাহরণে নেই, খুব দুর্ভাগ্যজনক কী)। GTranslate.translateএটি কেবল একটি সুবিধাজনক পদ্ধতি GTranslate::Translator#perform, এটি গোপন করার কোনও সত্যিকারের লাভ নেই, যদি এটি সম্ভব ছিল।
michelpm

28
আমি নিশ্চিত না যে এখানে ক্লাস করে কী অর্জন করা হয়েছে। যদি লক্ষ্যটির একটি ব্যক্তিগত মডিউল পদ্ধতি থাকে তবে এটি লক্ষ্য পূরণ করে না। কারণ আপনি GTranslate :: Translator.new.perfor কল করে মডিউলটির বাইরে থেকে "পারফর্ম" পদ্ধতিটি অ্যাক্সেস করতে পারেন। অন্য শব্দে, এটি ব্যক্তিগত নয়।
জ্যাক শো

1
@jschorr আমি মনে করি ওপ এবং এই উত্তরটি কোনও ব্যক্তিগত পদ্ধতি বা মডিউল পদ্ধতি তৈরির উদ্দেশ্যে, উদাহরণ পদ্ধতি নয়। এছাড়াও, self.translateশ্রেণি / মডিউল পদ্ধতির ঘোষণা হিসাবে এটি কোনও উদাহরণ পদ্ধতি ব্যক্তিগত রাখবে না ।
কনসোলবক্স

5
GTranslate::Translator.new.perform(text)- দোষী সাব্যস্ত, তবে ব্যক্তিগত নয়!
অবহেলমান

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

রুবি ২.১ বা আরও নতুন:

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

আমি এই সম্পর্কে অবগত ছিল না। পদ্ধতিটির সংজ্ঞা দেওয়ার আগেও কি এটি কাজ করবে private?
মার্নেন লাইবো-কোসার

7
@ জ্যাকোপারের উত্তর সহ এই উত্তরটি আসল সমাধান। @ মার্নেনলাইবো-কোসার এটি করেন না। আপনি আরও জবাবদিহি এবং ইন্ডেন্টেশন ব্যয় করে অন্য উত্তরটি বিবেচনা করতে পারেন। এটি আসলে কারও কারও কাছে পছন্দসই সমাধান হতে পারে। (কেবলমাত্র রেফারেন্সের জন্য
জবাব দিন

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
এটি গ্রহণযোগ্য উত্তর হওয়া উচিত। আমার মতে পরিষ্কার এবং মূর্তিমান।
মার্টিন নায়াগা

@ মার্টিননাইগায় এই include Writerঅপশন না থাকার অপূর্ণতা রয়েছে !
ইউলিস বিএন 18

28

কোনও মডিউল মিশ্রিত হওয়ার পরে আপনি অভিনব জিনিসগুলি করতে "অন্তর্ভুক্ত" পদ্ধতিটি ব্যবহার করতে পারেন you আপনি যা চান তা সম্পর্কে এটি করে:

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
@ ক্রাইস্টार्क: এই সিনট্যাক্সটি কেবলমাত্র মডিউলগুলিতে বিদ্যমান যা অ্যাক্টিভসপোর্ট প্রসারিত করে: যদি আমি ভুল না করি তবে উদ্বেগ প্রকাশ করুন। অর্থাত্ এটি একটি রেলের জিনিস।
ওয়াজ

11

দুর্ভাগ্যক্রমে, privateশুধুমাত্র উদাহরণ পদ্ধতিতে প্রযোজ্য। শ্রেণিতে ব্যক্তিগত "স্থিতিশীল" পদ্ধতিগুলি পাওয়ার সাধারণ উপায় হ'ল কিছু করা:

class << self
  private

  def foo()
   ....
  end
end

স্বীকারোক্তিটি আমি মডিউলগুলিতে এটি করে খেলিনি।


7
এটি সত্য নয়। আপনার ব্যক্তিগত ক্লাস পদ্ধতি এবং ব্যক্তিগত মডিউল পদ্ধতি থাকতে পারে।
মাইকাইকগ্টো

আপনার কাছে প্রাইভেট ক্লাসের পদ্ধতি থাকতে পারে, তবে এটি কেবল .fooএকটি ব্যক্তিগত শ্রেণির পদ্ধতি তৈরি করবে না : "ব্যক্তিগত; ডিএফ সেল্ফ.ফু ()"
অরি

@mikeycgto প্রাইভেট ক্লাস পদ্ধতি এবং বেসরকারী মডিউল পদ্ধতির মধ্যে পার্থক্যটি বিস্তারিতভাবে দেখানোর জন্য যত্ন? কারণ আমি মনে করি তারা ঠিক একই রকম। উল্লেখ্য যে উভয়ই privateএবং private_class_methodএর মালিকানাধীন Moduleনয় Class। এই কোডটি উপায় দ্বারা কাজ করে এবং এটি ব্যবহারের বিকল্প private_class_method
কনসোলবক্স

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.


ল্যাম্বডাস পদ্ধতিগুলির মতো একদম নয়। ল্যাম্বডাস ধরণের হয় Proc, তবে পদ্ধতিগুলি ধরণের Method
মাইকেল ডারস্ট

1
গ্লোবাল ভেরিয়েবলগুলি খারাপ
ache Champion

@ਚੇম্পিয়ান, আপনি তাদের কোথায় দেখছেন?
নাকিলন

@ নাকিলন আমার ক্ষমা প্রার্থনা করুন, আপনার উত্তরটি সম্পাদনা করুন যদি আপনি চান যে আমি আমার ভোট বাতিল করতে চাই
অচম্পিমন

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"

Module.new এবং 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)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.