রুবি শ্রেণীর উদাহরণ ভেরিয়েবল বনাম শ্রেণি ভেরিয়েবল


179

আমি " রুবি ইনস্ট্যান্স ভেরিয়েবল কখন সেট হয়ে যায়? " পড়ি তবে ক্লাস ইনস্ট্যান্স ভেরিয়েবলগুলি কখন ব্যবহার করতে হয় সে বিষয়ে আমি দুজনের মনে।

শ্রেণীর ভেরিয়েবলগুলি কোনও শ্রেণীর সমস্ত অবজেক্ট দ্বারা ভাগ করা হয়, ইনস্ট্যান্স ভেরিয়েবলগুলি একটি বস্তুর অন্তর্ভুক্ত। ক্লাস ইনস্ট্যান্স ভেরিয়েবলগুলি ব্যবহার করার মতো খুব বেশি জায়গা অবশিষ্ট নেই যদি আমাদের ক্লাস ভেরিয়েবল থাকে।

কেউ কি এই দুটিয়ের মধ্যে পার্থক্য ব্যাখ্যা করতে পারেন এবং কখন তাদের ব্যবহার করবেন?

এখানে একটি কোড উদাহরণ:

class S
  @@k = 23
  @s = 15
  def self.s
    @s
  end
  def self.k
     @@k
  end

end
p S.s #15
p S.k #23

আমি এখন বুঝতে পারি, ক্লাস ইনস্ট্যান্স ভেরিয়েবলগুলি উত্তরাধিকার শৃঙ্খলা বরাবর পাস হয় না!

উত্তর:


276

ক্লাসে ইনস্ট্যান্স ভেরিয়েবল:

class Parent
  @things = []
  def self.things
    @things
  end
  def things
    self.class.things
  end
end

class Child < Parent
  @things = []
end

Parent.things << :car
Child.things  << :doll
mom = Parent.new
dad = Parent.new

p Parent.things #=> [:car]
p Child.things  #=> [:doll]
p mom.things    #=> [:car]
p dad.things    #=> [:car]

শ্রেণি পরিবর্তনশীল:

class Parent
  @@things = []
  def self.things
    @@things
  end
  def things
    @@things
  end
end

class Child < Parent
end

Parent.things << :car
Child.things  << :doll

p Parent.things #=> [:car,:doll]
p Child.things  #=> [:car,:doll]

mom = Parent.new
dad = Parent.new
son1 = Child.new
son2 = Child.new
daughter = Child.new

[ mom, dad, son1, son2, daughter ].each{ |person| p person.things }
#=> [:car, :doll]
#=> [:car, :doll]
#=> [:car, :doll]
#=> [:car, :doll]
#=> [:car, :doll]

ক্লাসে উদাহরণস্বরূপ ভেরিয়েবলের সাথে (সেই শ্রেণীর উদাহরণ নয়) আপনি সাব-ক্লাস না করে সে শ্রেণিতে সাধারণ কিছু সঞ্চয় করতে পারেন স্বয়ংক্রিয়ভাবে সেগুলিও পেয়ে যায় (এবং তদ্বিপরীত)। ক্লাস ভেরিয়েবলের সাথে, আপনার self.classকোনও ইনস্ট্যান্স অবজেক্ট থেকে না লেখার সুবিধা রয়েছে এবং (যখন পছন্দসই হয়) আপনি ক্লাস শ্রেণিবদ্ধ জুড়ে স্বয়ংক্রিয়ভাবে ভাগ করে নেবেন।


এগুলি একক উদাহরণে একত্রিত করা উদাহরণস্বরূপ উদাহরণসমূহের ভেরিয়েবলগুলিও কভার করে:

class Parent
  @@family_things = []    # Shared between class and subclasses
  @shared_things  = []    # Specific to this class

  def self.family_things
    @@family_things
  end
  def self.shared_things
    @shared_things
  end

  attr_accessor :my_things
  def initialize
    @my_things = []       # Just for me
  end
  def family_things
    self.class.family_things
  end
  def shared_things
    self.class.shared_things
  end
end

class Child < Parent
  @shared_things = []
end

এবং তারপরে কর্মে:

mama = Parent.new
papa = Parent.new
joey = Child.new
suzy = Child.new

Parent.family_things << :house
papa.family_things   << :vacuum
mama.shared_things   << :car
papa.shared_things   << :blender
papa.my_things       << :quadcopter
joey.my_things       << :bike
suzy.my_things       << :doll
joey.shared_things   << :puzzle
suzy.shared_things   << :blocks

p Parent.family_things #=> [:house, :vacuum]
p Child.family_things  #=> [:house, :vacuum]
p papa.family_things   #=> [:house, :vacuum]
p mama.family_things   #=> [:house, :vacuum]
p joey.family_things   #=> [:house, :vacuum]
p suzy.family_things   #=> [:house, :vacuum]

p Parent.shared_things #=> [:car, :blender]
p papa.shared_things   #=> [:car, :blender]
p mama.shared_things   #=> [:car, :blender]
p Child.shared_things  #=> [:puzzle, :blocks]  
p joey.shared_things   #=> [:puzzle, :blocks]
p suzy.shared_things   #=> [:puzzle, :blocks]

p papa.my_things       #=> [:quadcopter]
p mama.my_things       #=> []
p joey.my_things       #=> [:bike]
p suzy.my_things       #=> [:doll] 

@ ফ্রোনজ আপনার কোডে উল্লিখিত সেলফ স্টাথিংস এবং সেলফ.গ্লাসের মধ্যে পার্থক্য কী?
সাইবার্গ

1
@cyborg বর্তমান স্কোপটিতে self.thingsএকটি পদ্ধতি উল্লেখ করেছে things(কোনও শ্রেণীর উদাহরণের ক্ষেত্রে এটি উদাহরণের পদ্ধতি হবে), যেখানে বর্তমান ক্ষেত্রের শ্রেণি থেকে self.class.thingsকোনও thingsপদ্ধতি উল্লেখ করা হয়েছে (আবার কোনও শ্রেণীর উদাহরণের অর্থ এটির অর্থ হবে) ক্লাস পদ্ধতি)।
গ্রাফজান

সুন্দর ব্যাখ্যা।
aliahme922

30

আমি বিশ্বাস করি মূল (একমাত্র?) আলাদা হ'ল উত্তরাধিকার:

class T < S
end

p T.k
=> 23

S.k = 24
p T.k
=> 24

p T.s
=> nil

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


1
এটিই কেবল পার্থক্য নয়। "ভাগ করা" বনাম "উদাহরণ" উত্তরাধিকারের চেয়ে আরও বেশি এগিয়ে যায়। আপনি উদাহরণস্বরূপ গেটারগুলি রাখলে আপনি পাবেন S.new.s => nilএবং পাবেন S.new.k => 23
আন্দ্রে ফিগুয়েরেদো

27

উৎস

উদাহরণ পদ্ধতিতে উপলভ্যতা

  • শ্রেণীর উদাহরণের ভেরিয়েবলগুলি কেবল শ্রেণির পদ্ধতিগুলিতে উপলভ্য হয় এবং উদাহরণ পদ্ধতিগুলির জন্য নয়।
  • বর্গ ভেরিয়েবল উভয় উদাহরণ পদ্ধতি এবং শ্রেণিক পদ্ধতিতে উপলব্ধ।

Inheritability

  • শ্রেণীর উদাহরণ ভেরিয়েবলগুলি উত্তরাধিকার শৃঙ্খলে হারিয়ে যায়।
  • ক্লাস ভেরিয়েবল হয় না।
class Vars

  @class_ins_var = "class instance variable value"  #class instance variable
  @@class_var = "class variable value" #class  variable

  def self.class_method
    puts @class_ins_var
    puts @@class_var
  end

  def instance_method
    puts @class_ins_var
    puts @@class_var
  end
end

Vars.class_method

puts "see the difference"

obj = Vars.new

obj.instance_method

class VarsChild < Vars


end

VarsChild.class_method

15

অন্যরা যেমন বলেছে, শ্রেণি ভেরিয়েবলগুলি একটি নির্দিষ্ট শ্রেণি এবং তার উপক্লাসগুলির মধ্যে ভাগ করা হয়। শ্রেণীর উদাহরণ ভেরিয়েবলগুলি এক শ্রেণীর অন্তর্গত; এর সাবক্লাসগুলি পৃথক।

কেন এই আচরণ বিদ্যমান? ঠিক আছে, রুবির প্রতিটি জিনিস একটি বস্তু এমনকি ক্লাস। এর অর্থ হ'ল প্রতিটি শ্রেণীর সাথে সম্পর্কিত বর্গের একটি বস্তু রয়েছে Class(বা বরং এটি একটি সাবক্লাস Class)। (যখন আপনি বলেন class Foo, আপনি সত্যই একটি ধ্রুবক ঘোষণা করছেন Fooএবং এটিতে কোনও শ্রেণি অবজেক্ট বরাদ্দ করছেন )) এবং প্রতিটি রুবি অবজেক্টে উদাহরণ ভেরিয়েবল থাকতে পারে, সুতরাং শ্রেণি অবজেক্টগুলিতেও উদাহরণ ভেরিয়েবল থাকতে পারে।

ঝামেলাটি হ'ল, ক্লাস অবজেক্টগুলিতে উদাহরণস্বরূপ ভেরিয়েবলগুলি আপনি সাধারণত বর্গ ভেরিয়েবলগুলি আচরণ করতে চান তেমন আচরণ করে না। আপনি সাধারণত একটি সুপারক্লাসে সংজ্ঞায়িত একটি শ্রেণীর ভেরিয়েবলকে তার সাবক্লাসের সাথে ভাগ করে নিতে চান, তবে উদাহরণ ভেরিয়েবলগুলি কীভাবে কাজ করে তা নয় c সাবক্লাসটির নিজস্ব শ্রেণি অবজেক্ট রয়েছে এবং এই শ্রেণীর অবজেক্টটির নিজস্ব উদাহরণ ভেরিয়েবল রয়েছে। সুতরাং আপনি যে আচরণটি চান তার সাথে তারা পৃথক শ্রেণীর ভেরিয়েবলগুলি প্রবর্তন করেছিলেন।

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


ক্লাস ভেরিয়েবল জাভাতে স্ট্যাটিক ভেরিয়েবলের মতো?
কিক বাটভস্কি

3

অফিসিয়াল রুবি এফএকিউ: ক্লাস ভেরিয়েবল এবং ক্লাস ইনস্ট্যান্স ভেরিয়েবলের মধ্যে পার্থক্য কী?

মূল পার্থক্য হ'ল উত্তরাধিকার সম্পর্কিত আচরণ: শ্রেণি ভেরিয়েবলগুলি একটি শ্রেণি এবং তার সমস্ত উপশ্রেণীর মধ্যে ভাগ করা হয়, যখন শ্রেণীর উদাহরণের ভেরিয়েবলগুলি কেবল একটি নির্দিষ্ট শ্রেণীর অন্তর্ভুক্ত।

শ্রেণি ভেরিয়েবলগুলি কোনওভাবে উত্তরাধিকারের শ্রেণিবদ্ধের প্রেক্ষাপটে বৈশ্বিক পরিবর্তনশীল হিসাবে দেখা যায়, বৈশ্বিক ভেরিয়েবলগুলির সাথে আসা সমস্ত সমস্যার সাথে। উদাহরণস্বরূপ, কোনও শ্রেণীর ভেরিয়েবল (দুর্ঘটনাক্রমে) এর যে কোনও সাবক্লাস দ্বারা পুনরায় নিয়োগ দেওয়া হতে পারে, অন্য সমস্ত শ্রেণিকে প্রভাবিত করে:

class Woof

  @@sound = "woof"

  def self.sound
    @@sound
  end
end

Woof.sound  # => "woof"

class LoudWoof < Woof
  @@sound = "WOOF"
end

LoudWoof.sound  # => "WOOF"
Woof.sound      # => "WOOF" (!)

অথবা, কোনও পূর্বপুরুষের ক্লাসটি পরে সম্ভবত পুনরায় খোলা এবং পরিবর্তিত হতে পারে, সম্ভবত আশ্চর্যজনক প্রভাব সহ:

class Foo

  @@var = "foo"

  def self.var
    @@var
  end
end

Foo.var  # => "foo" (as expected)

class Object
  @@var = "object"
end

Foo.var  # => "object" (!)

সুতরাং, আপনি কী করছেন তা সঠিকভাবে না জানলে এবং স্পষ্টভাবে এই ধরণের আচরণের প্রয়োজন হয় না, আপনার আরও ভাল ক্লাস উদাহরণ ভেরিয়েবলগুলি ব্যবহার করা উচিত।


2

সি ++ ব্যাকগ্রাউন্ডযুক্তদের ক্ষেত্রে, আপনি সি ++ সমমানের সাথে তুলনা করতে আগ্রহী হতে পারেন:

class S
{
private: // this is not quite true, in Ruby you can still access these
  static int    k = 23;
  int           s = 15;

public:
  int get_s() { return s; }
  static int get_k() { return k; }

};

std::cerr << S::k() << "\n";

S instance;
std::cerr << instance.s() << "\n";
std::cerr << instance.k() << "\n";

যেমন আমরা দেখতে পাচ্ছি, এটিও kএকটি staticপরিবর্তনশীল। এটি বিশ্বব্যাপী ভেরিয়েবলের মতো 100%, ক্লাসের মালিকানা ব্যতীত ( স্কোপড) সঠিক বলে)। এটি একইভাবে নামযুক্ত ভেরিয়েবলগুলির মধ্যে সংঘর্ষ এড়ানো সহজ করে তোলে। যে কোনও গ্লোবাল ভেরিয়েবলের মতো, সেই পরিবর্তনশীল ও পরিবর্তনের কেবল একটি উদাহরণ রয়েছে যা সর্বদা সবার কাছে দৃশ্যমান।

অন্য দিকে, s একটি অবজেক্ট নির্দিষ্ট মান। প্রতিটি বস্তুর নিজস্ব মূল্য রয়েছে। সি ++ এ, সেই ভেরিয়েবলটি অ্যাক্সেস করার জন্য আপনাকে অবশ্যই একটি উদাহরণ তৈরি করতে হবে। রুবিতে, ক্লাস সংজ্ঞাটি নিজেই শ্রেণীর একটি উদাহরণ (জাভাস্ক্রিপ্টে একে প্রোটোটাইপ বলা হয়), সুতরাং আপনি sঅতিরিক্ত তাত্ক্ষণিকতা ছাড়াই ক্লাস থেকে অ্যাক্সেস করতে পারেন । শ্রেণীর উদাহরণটি সংশোধন করা যেতে পারে, তবে পরিবর্তনটি sপ্রতিটি উদাহরণের (নির্দিষ্ট প্রতিটি বস্তুর S) জন্য নির্দিষ্ট হতে চলেছে । সুতরাং একটি পরিবর্তন করে অন্যের মান পরিবর্তন হবে না।


1

ক্লাস ইনস্ট্যান্স ভেরিয়েবলগুলি ব্যবহার করার জন্য এটি তাত্ক্ষণিকভাবে দরকারী বলে মনে হতে পারে, যেহেতু ক্লাস উদাহরণের ভেরিয়েবলটি সাবক্লাসের মধ্যে ভাগ করা হয় এবং সেগুলি সিঙ্গেলটন এবং উদাহরণ উভয় পদ্ধতির মধ্যে উল্লেখ করা যেতে পারে, তবে একটি অসাধারণ অসুবিধা রয়েছে। এগুলি ভাগ করা হয়েছে এবং তাই সাবক্লাসগুলি শ্রেণীর উদাহরণের পরিবর্তনশীলটির মান পরিবর্তন করতে পারে এবং বেস ক্লাসটি পরিবর্তনের দ্বারাও প্রভাবিত হবে যা সাধারণত অবাঞ্ছিত আচরণ:

class C
  @@c = 'c'
  def self.c_val
    @@c
  end
end

C.c_val
 => "c" 

class D < C
end

D.instance_eval do 
  def change_c_val
    @@c = 'd'
  end
end
 => :change_c_val 

D.change_c_val
(irb):12: warning: class variable access from toplevel
 => "d" 

C.c_val
 => "d" 

রেলগুলি ক্লাস_ট্রিবিউট নামে একটি সহজ পদ্ধতি প্রবর্তন করে। নামটি বোঝা যায়, এটি একটি শ্রেণি-স্তরের বৈশিষ্ট্য ঘোষণা করে যার মান সাবক্লাস দ্বারা উত্তরাধিকারসূত্রে প্রাপ্ত। ক্লাস_সট্রিবিউট মানটি সিঙ্গলটন এবং দৃষ্টান্ত পদ্ধতিতে উভয়ই অ্যাক্সেস করা যায়, যেমন শ্রেণীর উদাহরণ ভেরিয়েবলের ক্ষেত্রে। তবে, কারাগারে ক্লাস_অ্যাট্রিবিউটের সাথে বিশাল উপকার হল সাবক্লাসগুলি তাদের নিজস্ব মান পরিবর্তন করতে পারে এবং এটি পিতামাতার শ্রেণিকে প্রভাবিত করবে না।

class C
  class_attribute :c
  self.c = 'c'
end

 C.c
 => "c" 

class D < C
end

D.c = 'd'
 => "d" 

 C.c
 => "c" 

ভাল কল, আমি এই আগে ব্যবহার করা হয়নি। এটা কাজ মনে হয় যদিও আপনি পূর্বে লিখুন নিশ্চিত করা প্রয়োজন self.প্রত্যেক সময় আপনি অ্যাট্রিবিউট অ্যাক্সেস করতে চান c, যেমন self.c। দস্তাবেজগুলি বলে যে একটি default:প্যারামিটারটি পাস করা যেতে পারে class_attributeতবে আমি ঠিক যে পয়েন্টটির সাথে উল্লেখ করেছি তার কারণে এটি কাজ করছে বলে মনে হচ্ছে না self
ডেক্স

আপনি যখন "ক্লাস ইনস্ট্যান্স ভেরিয়েবলগুলি ব্যবহার করার জন্য এটি তাত্ক্ষণিকভাবে দরকারী মনে হতে পারে" বলছেন, তখন আমার মনে হয় আপনার "ক্লাস ভেরিয়েবল" বোঝানো হয়েছে, "শ্রেণীর উদাহরণের ভেরিয়েবলগুলি ঠিক নয়?" ( রুবি-lang.org/en/docamentation/faq/8/ দেখুন )। )
কিথ বেনেট

হ্যাঁ, এই উত্তরটি "শ্রেণীর উদাহরণের ভেরিয়েবলগুলি" এবং "শ্রেণীর ভেরিয়েবলগুলি" কে পুরোপুরি বিভ্রান্ত করে, যা প্রশ্নের পুরো বিষয়টি।
স্টিভো
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.