প্রাইভেট ক্লাস পদ্ধতি কীভাবে তৈরি করবেন?


216

একটি বেসরকারী শ্রেণি পদ্ধতি তৈরির এই পদ্ধতির কীভাবে কাজ হয়:

class Person

  def self.get_name
    persons_name
  end

  class << self

    private

    def persons_name
      "Sam"
    end
  end
end

puts "Hey, " + Person.get_name
puts "Hey, " + Person.persons_name  #=> raises "private method `persons_name' called for Person:Class (NoMethodError)"

তবে এটি করে না:

class Person

  def self.get_name
    persons_name
  end

  private

  def self.persons_name
    "Sam"
  end
end

puts "Hey, " + Person.get_name
puts "Hey, " + Person.persons_name

7
আমি এই নিবন্ধটি কেবলমাত্র প্রাইভেট ক্লাসের পদ্ধতি তৈরির বিষয়ে আলোচনা করে দেখেছি এবং এটি ভাল হয়েছে বলে মনে করেছি: জ্যাকিয়েসবেক.কম
নাথান লং

উত্তর:


265

privateআপনি যদি কোনও সুস্পষ্ট বস্তুর (আপনার ক্ষেত্রে self) কোনও পদ্ধতি নির্ধারণ করছেন তবে কাজ করছে বলে মনে হচ্ছে না । আপনি private_class_methodশ্রেণি পদ্ধতিগুলি ব্যক্তিগত (বা আপনার বর্ণনার মতো) হিসাবে সংজ্ঞায়িত করতে ব্যবহার করতে পারেন ।

class Person
  def self.get_name
    persons_name
  end

  def self.persons_name
    "Sam"
  end

  private_class_method :persons_name
end

puts "Hey, " + Person.get_name
puts "Hey, " + Person.persons_name

বিকল্পভাবে (রুবি ২.১+ এ), যেহেতু একটি পদ্ধতির সংজ্ঞা পদ্ধতিটির নামের প্রতীকটি প্রত্যাবর্তন করে, আপনি এটি নীচের হিসাবে এটি ব্যবহার করতে পারেন:

class Person
  def self.get_name
    persons_name
  end

  private_class_method def self.persons_name
    "Sam"
  end
end

puts "Hey, " + Person.get_name
puts "Hey, " + Person.persons_name

105

এক্সিআর লিখেছেন:

রুবির এমন আচরণ সত্যিই হতাশাব্যঞ্জক। মানে আপনি যদি ব্যক্তিগত বিভাগে চলে যান তবে এটি ব্যক্তিগত নয়। তবে আপনি যদি এটি << স্বতঃ শ্রেণিতে চলে যান তবে হঠাৎ এটি কার্যকর হয়। এটা ঠিক জঘন্য।

বিভ্রান্তি সম্ভবত এটি হতাশাজনক হতে পারে, কিন্তু এটি ঘৃণ্য অবশ্যই না।

এটা নিখুঁত জ্ঞান করে তোলে একবার আপনি রুবি এর অবজেক্ট মডেল বুঝতে এবং সংশ্লিষ্ট পদ্ধতি প্রবাহিত লুকআপ , বিশেষত যখন বিবেচনা গ্রহণ যে privateহয় না একটি অ্যাক্সেস / দৃশ্যমানতা পরিবর্তক, কিন্তু আসলে একটি পদ্ধতি কল (তার প্রাপক হিসাবে বর্গ সঙ্গে) আলোচনা এখানে ... রুবির কোনও "ব্যক্তিগত বিভাগ" বলে কিছু নেই

ব্যক্তিগত উদাহরণ পদ্ধতিগুলি সংজ্ঞায়িত করার জন্য, আপনি privateপরবর্তী শ্রেণীবদ্ধ পদ্ধতিগুলি বেসরকারীতে ডিফল্ট দৃশ্যমানতা সেট করার জন্য উদাহরণটির শ্রেণিতে কল করুন ... এবং তাই শ্রেণীর ক্লাসে ডেকে প্রাইভেট ক্লাসের পদ্ধতিগুলি সংজ্ঞায়িত করার জন্য এটি সঠিক ধারণা দেয় private। এর মেটাক্লাস

অন্যান্য মূলধারার, স্ব-ঘোষিত ওও ভাষাগুলি আপনাকে কম বিভ্রান্তিকর সিনট্যাক্স দিতে পারে, তবে আপনি অবশ্যই এটি রুবীর রূপক সুবিধার শক্তি ছাড়াই বিভ্রান্তিকর এবং কম সামঞ্জস্যপূর্ণ (অসঙ্গত?) অবজেক্ট মডেলের বিরুদ্ধে বাণিজ্য করেন ।


সুতরাং আমি যদি সঠিকভাবে বুঝতে পারি তবে রুবি নিজেই কোনও অ্যাক্সেস মডিফায়ার কীওয়ার্ড (পাবলিক, প্রাইভেট এবং সুরক্ষিত) না পেয়ে বরং অ্যাক্সেস মডিফায়ার পদ্ধতিতে (পাবলিক, প্রাইভেট, সুরক্ষিত) থাকতে পারেন? এটি কি ম্যাটজকে যথাযথ কীওয়ার্ড অ্যাক্সেস সংশোধক প্রয়োগ করার জন্য রুবি বাগ ট্র্যাকারের উপরে আনতে হবে বা এটি প্রত্যাশিত আচরণ?
এডওয়ার্ড

13
@Edward এটা পরিকল্পিত যে ভাবে junichiito.blogspot.co.uk/2012/03/... । "যথাযথ" কেন?
আইয়েন

1
এর থেকে অনুসরণ করে না করে বরং private_class_method :method_nameআপনি করতে পারেন private_class_method def method_name...
বিজেটি 38

send(private_method)বস্তুর বাইরেও অ্যাক্সেসযোগ্য।
স্টিভেনস্পিল

1
@ বিজেটি 38 কেবল স্পষ্টতার জন্য, এটি হবেprivate_class_method def self.method_name
টম

78

ডিফল্টরূপে সমস্ত শ্রেণীর পদ্ধতিগুলি সর্বজনীন। তাদের ব্যক্তিগত করার জন্য আপনি মডিউল # ব্যক্তিগত_ক্লাস_মোথাল যেমন @ টাজওয়ালাস লিখেছেন বা তাদের আলাদাভাবে সংজ্ঞা দিতে পারেন যেমন আপনি করেছেন:

class << self

  private

  def method_name
    ...
  end
end

class << selfস্ব-এর সিঙ্গলটন শ্রেণি খোলে, যাতে বর্তমানের স্ব-বস্তুর জন্য পদ্ধতিগুলি পুনরায় সংজ্ঞায়িত করা যায়। এটি শ্রেণি / মডিউল ("স্ট্যাটিক") পদ্ধতিটি সংজ্ঞায়িত করতে ব্যবহৃত হয়। কেবল সেখানে, ব্যক্তিগত পদ্ধতিগুলি সংজ্ঞায়িত করা আপনাকে ব্যক্তিগত শ্রেণীর পদ্ধতিগুলি দেয়।


17

কেবলমাত্র সম্পূর্ণতার জন্য, আমরা একটি পৃথক লাইনে ব্যক্তিগত_ক্লাস_মাদুরি ঘোষণা এড়াতে পারি। আমি ব্যক্তিগতভাবে এই ব্যবহারটি পছন্দ করি না তবে এটি জেনে রাখা ভাল যে এটি বিদ্যমান।

private_class_method  def self.method_name
 ....
end

5

আমিও, রুবিকে (বা কমপক্ষে এটি সম্পর্কে আমার জ্ঞান) এই অঞ্চলে চিহ্নের সংক্ষিপ্ত সন্ধান করি। উদাহরণস্বরূপ নীচেরগুলি আমি যা চাই তা করে তবে আনাড়ি,

class Frob
    attr_reader :val1, :val2

    Tolerance = 2 * Float::EPSILON

    def initialize(val1, val2)
        @val2 = val1
        @val2 = val2
        ...
    end

    # Stuff that's likely to change and I don't want part
    # of a public API.  Furthermore, the method is operating
    # solely upon 'reference' and 'under_test' and will be flagged as having
    # low cohesion by quality metrics unless made a class method.
    def self.compare(reference, under_test)
        # special floating point comparison
        (reference - under_test).abs <= Tolerance
    end
    private_class_method :compare

    def ==(arg)
        self.class.send(:compare, val1, arg.val1) &&
        self.class.send(:compare, val2, arg.val2) &&
        ...
    end
end

উপরের কোডটির সাথে আমার সমস্যাগুলি হ'ল রুবি সিনট্যাক্সের প্রয়োজনীয়তা এবং আমার কোড মানের মেট্রিকগুলি জটিল কোডের জন্য ষড়যন্ত্র করে। কোডটি আমার যেমন চাই তেমন কাজ করতে এবং মেট্রিকগুলিকে শান্ত করার জন্য, আমাকে তুলনা () একটি শ্রেণি পদ্ধতিতে করতে হবে। যেহেতু আমি এটি ক্লাসের 'পাবলিক এপিআই'র অংশ হতে চাই না, তাই এটি আমার ব্যক্তিগত হওয়া দরকার, তবুও' ব্যক্তিগত 'নিজেই কাজ করে না। পরিবর্তে আমি 'প্রাইভেট_ক্লাস_মোথার' বা এই জাতীয় কিছু কাজের জন্য বাধ্য। এর ফলে, '== ()' তে পরীক্ষিত প্রতিটি চলকটির জন্য 'সেলফক্লাস.সেন্ড (: তুলনা করুন ...') প্রয়োগ করা জোর করে Now এখন এটি কিছুটা অপ্রয়োজনীয়।


আপনার পাঠানোর যে বিষয়টি ব্যবহার করা দরকার তা শ্রেণিক পদ্ধতিগুলিকে ব্যক্তিগত হিসাবে চিহ্নিত করে "কীভাবে" তার কোনও সম্পর্ক নেই। "বাইরের" থেকে ব্যক্তিগত পদ্ধতিগুলি কল করা যায় না।
পাস্কাল

4

বর্গ সংজ্ঞা ব্লকের ভিতরে ইনস্ট্যান্স পদ্ধতিগুলি সংজ্ঞায়িত করা হয়। শ্রেণীর পদ্ধতিগুলি কোনও শ্রেণীর একক ক্লাসে সিঙ্গলটন পদ্ধতি হিসাবে সংজ্ঞায়িত হয়, এটি অনানুষ্ঠানিকভাবে "মেটাক্লাস" বা "আইজেনক্লাস" নামেও পরিচিত। privateকোনও কীওয়ার্ড নয়, তবে একটি পদ্ধতি ( মডিউল # ব্যক্তিগত )।

এটি কোনও পদ্ধতিতে কল self#private/ A#privateযা "টগল" করে সমস্ত আগমনী পদ্ধতি পদ্ধতির সংজ্ঞাগুলির জন্য টগল না করা পর্যন্ত ব্যক্তিগত অ্যাক্সেসটিকে চালু করে:

class A
  private
    def instance_method_1; end
    def instance_method_2; end
    # .. and so forth
end

যেমন পূর্বে উল্লেখ করা হয়েছে, শ্রেণি পদ্ধতিগুলি সত্যই সিঙ্গলটন পদ্ধতিতে সিঙ্গলটন শ্রেণিতে সংজ্ঞায়িত হয়।

def A.class_method; end

বা এ এর ​​বেনামী, সিঙ্গলটন শ্রেণীর সংজ্ঞা বডি খুলতে একটি বিশেষ বাক্য গঠন ব্যবহার করে:

class << A
  def class_method; end
end

"বার্তা প্রাইভেট" - স্ব - অভ্যন্তরের class Aক্লাস অবজেক্ট এ এর ​​স্বীকৃতি class << Aহ'ল ব্লকের অভ্যন্তরে স্ব এক অন্য বস্তু, সিঙ্গলটন শ্রেণি।

নিম্নলিখিত উদাহরণটি বাস্তবে কল হিসাবে দুটি পৃথক প্রাপক বা লক্ষ্যবস্তু ব্যবহার করে প্রাইভেট নামে দুটি পৃথক পদ্ধতি কল করে। প্রথম অংশে, আমরা একটি ব্যক্তিগত উদাহরণ পদ্ধতি ("ক্লাস এ") সংজ্ঞায়িত করি, পরে আমরা একটি প্রাইভেট ক্লাস পদ্ধতি সংজ্ঞায়িত করি (আসলে এটি এ এর ​​সিঙ্গলটন শ্রেণীর অবজেক্টে একটি সিঙ্গলটন পদ্ধতি)।

class A
  # self is A and private call "A.private()"
  private def instance_method; end

  class << self
    # self is A's singleton class and private call "A.singleton_class.private()"
    private def class_method; end
  end
end

এখন, এই উদাহরণটি কিছুটা আবার লিখুন:

class A
  private
    def self.class_method; end
end

আপনি [যে রুবি ভাষার ডিজাইনাররা] ভুলটি দেখতে পাচ্ছেন? আপনি এ এর ​​আগত উদাহরণ পদ্ধতিগুলির জন্য ব্যক্তিগত অ্যাক্সেসে টগল করুন, তবে একক ক্লাস, সিঙ্গলটন শ্রেণিতে একটি সিঙ্গলটন পদ্ধতি ঘোষণা করতে এগিয়ে যান।


-1

রুবি মনে হচ্ছে একটি দুর্বল সমাধান সরবরাহ করেছে। ব্যাখ্যা করতে, একটি সাধারণ সি ++ উদাহরণ দিয়ে শুরু করুন যা ব্যক্তিগত শ্রেণীর পদ্ধতিতে অ্যাক্সেস দেখায়:

#include <iostream>

class C
{
    public:
        void instance_method(void)
        {
            std::cout << "instance method\n";
            class_method();  // !!! LOOK !!! no 'send' required. We can access it
                             // because 'private' allows access within the class
        }
    private:
        void static class_method(void) { std::cout << "class method\n"; }
};

int main()
{
    C c;

    c.instance_method(); // works
    // C::class_method() does not compile - it's properly private
    return 0;
}

উপরের দিকে চলছে

   % ./a.out
   instance method
   class method

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

inst.pvt_method  # FAILS
pvt_method # WORKS only within the class (good)

এটি বেসরকারী উদাহরণ পদ্ধতিগুলির জন্য ঠিক আছে, তবে ব্যক্তিগত শ্রেণির পদ্ধতিতে সমস্যা সৃষ্টি করে।

আমি চাই রুবি এভাবে কাজ করবে:

class C
    def instance_method
        STDOUT << "instance method\n"

        # Simple access to the private class method would be nice:
        class_method   # DOES NOT WORK. RUBY WON'T FIND THE METHOD
        C.class_method # DOES NOT WORK. RUBY WON'T ALLOW IT

        # ONLY THIS WORKS. While I am happy such capability exists I think
        # the way 'send' should be used is when the coder knows he/she is
        # doing a no-no.  The semantic load on the coder for this is also
        # remarkably clumsy for an elegant language like ruby.
        self.class.send(:class_method)
    end

    private_class_method def self.class_method() STDOUT << "class method\n"; end
end

কিন্তু হায় আফসোস, উপরের কাজ করে না। কেউ কি আরও ভাল উপায় জানেন?

আমি যখন কোনও পদ্ধতির আগে 'প্রেরণ' দেখি তখন কোডটি এপিআইয়ের ডিজাইনারের উদ্দেশ্য লঙ্ঘন করছে তার একটি স্পষ্ট লক্ষণ, তবে এই ক্ষেত্রে নকশাকে বিশেষত ক্লাসের একটি উদাহরণ পদ্ধতিতে প্রাইভেট ক্লাস পদ্ধতি কল করতে হবে।


-14

রুবি হিসাবে 2.3.0

class Check
  def self.first_method
    second_method
  end

  private
  def self.second_method
    puts "well I executed"
  end
end

Check.first_method
#=> well I executed

আমি private def self.second_methodপ্রতিটি পদ্ধতির স্বরলিপি দেওয়ার আগে এটি চেষ্টা করছিলাম , যা আমার রুবি ২.৩.৩ এ কাজ করে না। তবে এই স্বরলিপিটি আমার পক্ষে কাজ করে।
এমিল ভ্রিজডাগস

11
এটি ভুল, কারণ কলিং Check.second_methodকোনও সমস্যা ছাড়াই কাজ করবে, সুতরাং এটি আসলে ব্যক্তিগত নয়।
দেইউইন

1
এটি চেষ্টা করে কাজ করবে নাprivate_class_method :second_method
কিং সাবারি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.