রুবি: উদাহরণ থেকে ক্লাস পদ্ধতি কল করা


347

রুবিতে, আপনি কীভাবে সেই শ্রেণীর উদাহরণ থেকে কোনও ক্লাস পদ্ধতি কল করবেন? বলুন আমার আছে

class Truck
  def self.default_make
    # Class method.
    "mac"
  end

  def initialize
    # Instance method.
    Truck.default_make  # gets the default via the class's method.
    # But: I wish to avoid mentioning Truck. Seems I'm repeating myself.
  end
end

লাইনটি Truck.default_makeডিফল্টটি পুনরুদ্ধার করে। তবে উল্লেখ না করে Truckকি বলার উপায় আছে ? দেখে মনে হচ্ছে সেখানে হওয়া উচিত।

উত্তর:


563

ক্লাসের আক্ষরিক নাম উল্লেখ না করে একটি উদাহরণ পদ্ধতির ভিতরে আপনি কেবল কল করতে পারেন self.class.whatever

class Foo
    def self.some_class_method
        puts self
    end

    def some_instance_method
        self.class.some_class_method
    end
end

print "Class method: "
Foo.some_class_method

print "Instance method: "
Foo.new.some_instance_method

আউটপুট:

ক্লাস পদ্ধতি: ফু
দৃষ্টান্ত পদ্ধতি: ফু

7
উদাহরণ থেকে ক্লাস পদ্ধতিতে কল করতে আমি রুবিতে কিছু শর্টকাট দেখতে চাই। অর্থাত:> স্বতঃ_ক্লাসের পরিবর্তে কিছু_ক্লাস_মোথিক.সোম_ক্লাস_মোথোড
ফোয়েট

7
যদিও এটি সঠিক উত্তর, এটি একটি লজ্জার বিষয় যে "ট্রাক" নামে শ্রেণীর নামটির চেয়ে "সেলফক্লাস" বেশি টাইপ করা এবং পড়া সহজ। ওহ ভাল ....
ম্যাট কনোলি

22
@MattConnolly, এটা আত্মীয় আপনার বর্গ নাম হয় তবে দয়া হয় SalesforceSyncJobতাহলে এটি খাটো;)
drewish

29
@ ম্যাটকননলি, self.classআপনি যদি শ্রেণীর নামকরণ করতে চান তবে অনুসন্ধান / প্রতিস্থাপনের প্রয়োজনীয়তাও হ্রাস করে ।
গাস শর্টজ

8
পছন্দ করুন এছাড়াও, একটি সাবক্লাস থাকলে self.class আরও ভাল কাজ করে।
ম্যাট কনোলি

183

ব্যবহার self.class.blahব্যবহার হিসাবে একই নয় ClassName.blahযখন এটা উত্তরাধিকার আসে।

class Truck
  def self.default_make
    "mac"
  end

  def make1
    self.class.default_make
  end

  def make2
    Truck.default_make
  end
end


class BigTruck < Truck
  def self.default_make
    "bigmac"
  end
end

ruby-1.9.3-p0 :021 > b=BigTruck.new
 => #<BigTruck:0x0000000307f348> 
ruby-1.9.3-p0 :022 > b.make1
 => "bigmac" 
ruby-1.9.3-p0 :023 > b.make2
 => "mac" 

58
এটি প্রশ্নের উত্তরের চেয়ে গ্রহণযোগ্য উত্তরের একটি প্রতিক্রিয়া বলে মনে হচ্ছে।
zhon

16
@ জোহন - সত্য, তবে কী ব্যবহার করবেন তা বিবেচনা করার সময় এটি এখনও দরকারী প্রসঙ্গে।
ম্যাট স্যান্ডার্স

1
@ ম্যাটস্যান্ডাররা কেবলমাত্র সে ক্ষেত্রে একটি মন্তব্য ব্যবহার করেন।
nandilugio

1
self.classউত্তরাধিকার রক্ষার জন্য @hlcs সঠিক। যদিও make1()এটি সংজ্ঞায়িত করা হয়েছে Truck, এটি BigTruck'র শ্রেণীর পদ্ধতিটি উল্লেখ করছে ।
কায়সার শহীদ

শ্রেণি_নাম.মোথড_নাম নিখুঁতভাবে কাজ করে
হুদা এম

14

উদাহরণ পদ্ধতির অভ্যন্তরে কোনও শ্রেণি পদ্ধতিতে অ্যাক্সেস পেতে নিম্নলিখিতগুলি করুন:

self.class.default_make

আপনার সমস্যার বিকল্প সমাধান এখানে দেওয়া হল:

class Truck

  attr_accessor :make, :year

  def self.default_make
    "Toyota"
  end

  def make
    @make || self.class.default_make
  end

  def initialize(make=nil, year=nil)
    self.year, self.make = year, make
  end
end

এখন আসুন আমাদের ক্লাসটি ব্যবহার করুন:

t = Truck.new("Honda", 2000)
t.make
# => "Honda"
t.year
# => "2000"

t = Truck.new
t.make
# => "Toyota"
t.year
# => nil

মেক একটি উদাহরণ পদ্ধতি হওয়া উচিত নয়। এটি আরও এক ধরণের কারখানা, এটি উদাহরণের চেয়ে ক্লাসের সাথে আবদ্ধ হওয়া উচিত
ফোয়েট

6
@phoet করতে শব্দ একটি গাড়ির করতে (টয়োটা, বগুড়া ইত্যাদি হিসাবে) উল্লেখ করে englishforums.com/English/AMakeOfCar/crcjb/post.htm । নামটি ব্যবহারকারীর প্রয়োজনীয়তার উপর ভিত্তি করে
হরিশ শেঠি

8

আপনার যদি ডেলিগেট পদ্ধতিতে অ্যাক্সেস থাকে তবে আপনি এটি করতে পারেন:

[20] pry(main)> class Foo
[20] pry(main)*   def self.bar
[20] pry(main)*     "foo bar"
[20] pry(main)*   end  
[20] pry(main)*   delegate :bar, to: 'self.class'
[20] pry(main)* end  
=> [:bar]
[21] pry(main)> Foo.new.bar
=> "foo bar"
[22] pry(main)> Foo.bar
=> "foo bar"

বিকল্পভাবে এবং সম্ভবত ক্লিনার যদি আপনার আরও বেশি থাকে তবে একটি বা দুটি পদ্ধতি আপনি ক্লাসে উদাহরণ দিতে চান এবং উদাহরণস্বরূপ:

[1] pry(main)> class Foo
[1] pry(main)*   module AvailableToClassAndInstance
[1] pry(main)*     def bar
[1] pry(main)*       "foo bar"
[1] pry(main)*     end  
[1] pry(main)*   end  
[1] pry(main)*   include AvailableToClassAndInstance
[1] pry(main)*   extend AvailableToClassAndInstance
[1] pry(main)* end  
=> Foo
[2] pry(main)> Foo.new.bar
=> "foo bar"
[3] pry(main)> Foo.bar
=> "foo bar"

সাবধানতার একটি শব্দ:

delegateক্লাস এবং উদাহরণে রাজ্য পরিবর্তন করে না এমন সবকিছু এলোমেলোভাবে করবেন না কারণ আপনি অদ্ভুত নাম সংঘর্ষের সমস্যাগুলির মধ্যে দৌড় শুরু করবেন। অল্প পরিমাণে এটি করুন এবং কেবলমাত্র আপনি পরীক্ষা করে দেখার পরে অন্য কিছুই স্কোয়াশড নয়।



5

আপনি এটি সঠিক উপায়ে করছেন শ্রেণি পদ্ধতি (সি ++ বা জাভাতে 'স্ট্যাটিক' পদ্ধতির অনুরূপ) উদাহরণটির অংশ নয়, তাই তাদের সরাসরি উল্লেখ করতে হবে।

এই নোটটিতে, আপনার উদাহরণে আপনাকে নিয়মিত পদ্ধতিতে 'ডিফল্ট_মেক' বানিয়ে আরও ভাল পরিবেশিত হতে হবে:

#!/usr/bin/ruby

class Truck
    def default_make
        # Class method.
        "mac"
    end

    def initialize
        # Instance method.
        puts default_make  # gets the default via the class's method.
    end
end

myTruck = Truck.new()

শ্রেণি পদ্ধতিগুলি ক্লাস ব্যবহার করে এমন ইউটিলিটি-টাইপ ফাংশনগুলির জন্য আরও দরকারী। উদাহরণ স্বরূপ:

#!/usr/bin/ruby

class Truck
    attr_accessor :make

    def default_make
        # Class method.
        "mac"
    end

    def self.buildTrucks(make, count)
        truckArray = []

        (1..count).each do
            truckArray << Truck.new(make)
        end

        return truckArray
    end

    def initialize(make = nil)
        if( make == nil )
            @make = default_make()
        else
            @make = make
        end
    end
end

myTrucks = Truck.buildTrucks("Yotota", 4)

myTrucks.each do |truck|
    puts truck.make
end

2
আমি একমত না যে default_makeএকটি উদাহরণ পদ্ধতি হওয়া উচিত। এমনকি যদি এই উদাহরণগুলির জন্য এটি সহজতর হয় তবে এটি সঠিক শব্দার্থবিজ্ঞান নয় - ডিফল্ট শ্রেণীর একটি পণ্য, শ্রেণীর অন্তর্গত কোনও বস্তু নয়।
পিটার

1
@ পিটার আপনি কি এটি সহজ কথায় ব্যাখ্যা করতে যত্ন নেবেন? আমি কেবল রুবি শিখছি এবং মহার উত্তরগুলি আমার কাছে নিখুঁত বলে মনে হচ্ছে।
মার্লেন টিবি

1
@ MarlenT.B। পিছনে ফিরে আমি নিশ্চিত যে এখানে খুব বেশি কিছু শেখার দরকার নেই - আমি কেবল এই পদ্ধতিটি রাখার সবচেয়ে ভাল জায়গাটি কোথায় তা নিয়েই তর্ক করছিলাম এবং আমি নিজের যুক্তিটি এতটা দৃ strongly়ভাবে কেনি না! :)
পিটার

2
আমিও একমত না কিছু শ্রেণিবদ্ধ কিনা তা "ইউটিলিটি" এর সাথে কিছুই করার নেই। এটি পদ্ধতিটি ক্লাসে ধারণামূলকভাবে প্রযোজ্য কিনা, বা সেই শ্রেণীর কোনও অবজেক্ট সম্পর্কে is উদাহরণস্বরূপ, প্রতিটি ট্রাকের আলাদা আলাদা সিরিয়াল নম্বর থাকে, সুতরাং সিরিয়াল_নাম্বার একটি উদাহরণ পদ্ধতি (আনুষঙ্গিক উদাহরণের পরিবর্তনশীল সহ)। অন্য যানবাহনের ধরণে (যা "ট্রাক" ফেরায়) একটি শ্রেণিবদ্ধ পদ্ধতি হওয়া উচিত কারণ এটি সমস্ত ট্রাকের সম্পত্তি, নির্দিষ্ট ট্রাক নয়
বিশ

3

আরো একটা:

class Truck
  def self.default_make
    "mac"
  end

  attr_reader :make

  private define_method :default_make, &method(:default_make)

  def initialize(make = default_make)
    @make = make
  end
end

puts Truck.new.make # => mac

1

আপনি কীভাবে এমন একটি পরিস্থিতি কার্যকর করতে পারেন _classযে কোনও পদ্ধতি প্রয়োগ করতে পারেন সে সম্পর্কে এখানে একটি কৌশল রয়েছে self.class। দ্রষ্টব্য: এটি উত্পাদন কোডটিতে ব্যবহার করবেন না, এটি স্বার্থের জন্য :)

থেকে: আপনি কি রুবিতে একজন কলারের প্রসঙ্গে কোডটি প্রকাশ করতে পারেন? এবং এটিও http://rubychallenger.blogspot.com.au/2011/07/caller-binding.html

# Rabid monkey-patch for Object
require 'continuation' if RUBY_VERSION >= '1.9.0'
class Object
  def __; eval 'self.class', caller_binding; end
  alias :_class :__
  def caller_binding
    cc = nil; count = 0
    set_trace_func lambda { |event, file, lineno, id, binding, klass|
      if count == 2
        set_trace_func nil
        cc.call binding
      elsif event == "return"
        count += 1
      end
    }
    return callcc { |cont| cc = cont }
  end
end

# Now we have awesome
def Tiger
  def roar
    # self.class.roar
    __.roar
    # or, even
    _class.roar
  end
  def self.roar
    # TODO: tigerness
  end
end

হতে পারে সঠিক উত্তরটি রুবির জন্য একটি প্যাচ জমা দেওয়া :)


-6

আপনার প্রশ্নের অনুরূপ, আপনি ব্যবহার করতে পারেন:

class Truck
  def default_make
    # Do something
  end

  def initialize
    super
    self.default_make
  end
end
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.