গতিশীল ধ্রুবক অ্যাসাইনমেন্ট


139
class MyClass
  def mymethod
    MYCONSTANT = "blah"
  end
end

আমাকে ত্রুটি দেয়:

সিনট্যাক্সেরর: গতিশীল ধ্রুবক অ্যাসাইনমেন্ট ত্রুটি

এটিকে কেন গতিশীল ধ্রুবক হিসাবে বিবেচনা করা হয়? আমি এটিতে একটি স্ট্রিং বরাদ্দ করছি।


34
ডায়নামিক কনস্ট্যান্ট শুকনো জলের মতো কিছু? :)
fl00r

39
এটি বলে না যে ধ্রুবকটি গতিশীল। এটি অ্যাসাইনমেন্টটি গতিশীল বলে।
sepp2k

উত্তর:


141

আপনার সমস্যাটি হ'ল প্রতিবার আপনি যে পদ্ধতিটি চালাচ্ছেন আপনি ধ্রুবকে একটি নতুন মান নির্ধারণ করছেন। এটি অনুমোদিত নয়, কারণ এটি ধ্রুবকটিকে অ-ধ্রুব করে তোলে; যদিও স্ট্রিংয়ের বিষয়বস্তু একই (মুহূর্তের জন্য, যে কোনওভাবে) একই হলেও, প্রতিটি বার পদ্ধতিটি বলা হওয়ার পরে প্রকৃত স্ট্রিং অবজেক্ট নিজেই আলাদা হয়। উদাহরণ স্বরূপ:

def foo
  p "bar".object_id
end

foo #=> 15779172
foo #=> 15779112

সম্ভবত আপনি যদি আপনার ব্যবহারের কেস ব্যাখ্যা করেন - আপনি কেন কোনও পদ্ধতিতে ধ্রুবকের মান পরিবর্তন করতে চান — আমরা আপনাকে আরও ভাল বাস্তবায়নে সহায়তা করতে পারি।

সম্ভবত আপনি বরং ক্লাসে একটি উদাহরণ পরিবর্তনশীল আছে?

class MyClass
  class << self
    attr_accessor :my_constant
  end
  def my_method
    self.class.my_constant = "blah"
  end
end

p MyClass.my_constant #=> nil
MyClass.new.my_method

p MyClass.my_constant #=> "blah"

আপনি যদি কোনও পদ্ধতিতে ধ্রুবকের মানটি সত্যিই পরিবর্তন করতে চান এবং আপনার ধ্রুবকটি স্ট্রিং বা অ্যারে হয় তবে আপনি আসলে 'প্রতারণা' করতে পারেন এবং #replaceঅবজেক্টটি আসলে পরিবর্তন না করেই কোনও নতুন মান গ্রহণের জন্য এই পদ্ধতিটি ব্যবহার করতে পারেন:

class MyClass
  BAR = "blah"

  def cheat(new_bar)
    BAR.replace new_bar
  end
end

p MyClass::BAR           #=> "blah"
MyClass.new.cheat "whee"
p MyClass::BAR           #=> "whee"

19
ওপি কখনও বলেনি যে তিনি ধ্রুবকের মান পরিবর্তন করতে চান তবে কেবল একটি মূল্য নির্ধারণ করতে চেয়েছিলেন। এই রুবি ত্রুটির দিকে ঘন ঘন ব্যবহারের ঘটনাটি হ'ল আপনি যখন অন্য রান-টাইম সম্পদগুলি (ভেরিয়েবল, কমান্ড-লাইন আর্গুমেন্ট, ENV) থেকে সাধারণত কোনও কনস্ট্রাক্টর যেমন থেকে কোনও পদ্ধতিতে মান তৈরি করেন def initialize(db,user,password) DB=Sequel.connect("postgres://#{user}:#{password}@localhost/#{db}") end। এটি এমন একটি ক্ষেত্রে যেখানে রুবির কোনও সহজ উপায় নেই।
আরনাউদ মিউরেট

2
@ আরনাউড মিউরেট সে ক্ষেত্রে আপনি @variableএকটি ধ্রুবক নয়, উদাহরণস্বরূপ পরিবর্তনশীল (যেমন ) চান । অন্যথায় আপনি DBযখনই এই শ্রেণীর কোনও নতুন উদাহরণ ইনস্ট্যান্ট করলেন প্রতিবার আপনাকে পুনরায় বরাদ্দ দেওয়া হবে ।
আজেদী 32

2
@ আজেদী 32 এই পরিস্থিতিটি সাধারণত সিক্যালের সাথে আমার উদাহরণের মতো পছন্দগুলি ডিজাইন না করে বাহ্যিক বাধা থেকে উদ্ভূত হয়। আমার বক্তব্যটি হ'ল একটি ধ্রুবককে একটি মান নির্ধারণের জন্য রুবি নির্দিষ্ট স্কোপগুলিতে অনুমতি দেয় এবং অন্যরা নয়। অ্যাসাইনমেন্টটি কখন সম্পাদন করতে হবে তা বুদ্ধিমানের সাথে বেছে নেওয়ার ক্ষেত্রে এটি বিকাশকারীদের কাছে ছিল। এতে রুবি বদলে গেল। সবার মঙ্গলজনক নয়।
অর্ণাড মিউরেট

2
@ আরনাউড মিউরেট আমি স্বীকার করব যে এর আগে আমি সিকেলটি আগে কখনও ব্যবহার করি নি তাই আমি এটি 100% নিশ্চিত করে বলতে পারি না, তবে সিক্যালের ডকুমেন্টেশনের দিকে ঝলক দেখছি আমি এমন কিছুই দেখতে পাচ্ছি না যা বলবে যে আপনি Sequel.connectস্থির নামযুক্ত ডিবিতে ফলাফল নির্ধারণের জন্য থাকতে পারেন । প্রকৃতপক্ষে, ডকুমেন্টেশনগুলি পরিষ্কারভাবে বলেছে যে এটি কেবল একটি সুপারিশ। এটি আমার কাছে বাহ্যিক প্রতিবন্ধকতার মতো শোনাচ্ছে না।
আজেদী 32

@ আজেদী 32 1) আমি কখনই লিখিনি যে (ধ্রুবকের নাম বা এমনকি আপনি এটি কোথাও রাখতে হয়েছিল) এটি কেবল উদাহরণ 2) আপনি সাধারণত কোনও গতিশীল প্রসঙ্গে না আসা পর্যন্ত আপনার সফ্টওয়্যারটির প্রয়োজনীয় তথ্য নাও থাকতে পারে ।
আরনাউদ মিউরেট

69

যেহেতু রুবির স্থির পরিবর্তনগুলি বোঝানো হচ্ছে না, রুবি আপনাকে কোডের কিছু অংশে তাদের অর্পণ করতে নিরুৎসাহিত করে যা অভ্যন্তরীণ পদ্ধতির মতো একাধিকবার কার্যকর করা হতে পারে।

সাধারণ পরিস্থিতিতে আপনার নিজের ক্লাসের ভিতরেই ধ্রুবকটি সংজ্ঞায়িত করা উচিত:

class MyClass
  MY_CONSTANT = "foo"
end

MyClass::MY_CONSTANT #=> "foo"

যদি কোনও কারণে আপনাকে কোনও পদ্ধতির অভ্যন্তরে ধ্রুবক সংজ্ঞায়িত করার প্রয়োজন হয় (সম্ভবত কোনও ধরণের রূপক ব্যবহারের জন্য), আপনি ব্যবহার করতে পারেন const_set:

class MyClass
  def my_method
    self.class.const_set(:MY_CONSTANT, "foo")
  end
end

MyClass::MY_CONSTANT
#=> NameError: uninitialized constant MyClass::MY_CONSTANT

MyClass.new.my_method
MyClass::MY_CONSTANT #=> "foo"

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

ক্লাস ভেরিয়েবল

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

পার্থক্যটি হ'ল শ্রেণি ভেরিয়েবলগুলি সংশোধনযোগ্য বলে বোঝানো হয় এবং তাই কোনও সমস্যা ছাড়াই অভ্যন্তরীণ পদ্ধতিতে নির্ধারিত হতে পারে।

class MyClass
  def self.my_class_variable
    @@my_class_variable
  end
  def my_method
    @@my_class_variable = "foo"
  end
end
class SubClass < MyClass
end

MyClass.my_class_variable
#=> NameError: uninitialized class variable @@my_class_variable in MyClass
SubClass.my_class_variable
#=> NameError: uninitialized class variable @@my_class_variable in MyClass

MyClass.new.my_method
MyClass.my_class_variable #=> "foo"
SubClass.my_class_variable #=> "foo"

শ্রেণীর বৈশিষ্ট্য

শ্রেণীর বৈশিষ্ট্যগুলি হ'ল "শ্রেণীর উপর উদাহরণ পরিবর্তনশীল" of তারা ক্লাস ভেরিয়েবলগুলির মতো কিছুটা আচরণ করে, তাদের মানগুলি সাবক্লাসের সাথে ভাগ না করা ব্যতীত।

class MyClass
  class << self
    attr_accessor :my_class_attribute
  end
  def my_method
    self.class.my_class_attribute = "blah"
  end
end
class SubClass < MyClass
end

MyClass.my_class_attribute #=> nil
SubClass.my_class_attribute #=> nil

MyClass.new.my_method
MyClass.my_class_attribute #=> "blah"
SubClass.my_class_attribute #=> nil

SubClass.new.my_method
SubClass.my_class_attribute #=> "blah"

উদাহরণস্বরূপ ভেরিয়েবল

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

class MyClass
  attr_accessor :instance_variable
  def my_method
    @instance_variable = "blah"
  end
end

my_object = MyClass.new
my_object.instance_variable #=> nil
my_object.my_method
my_object.instance_variable #=> "blah"

MyClass.new.instance_variable #=> nil

33

রুবিতে, কোনও পরিবর্তনশীল যার নাম মূলধনির সাথে শুরু হয় এটি একটি ধ্রুবক এবং আপনি কেবল একবার এটি বরাদ্দ করতে পারেন। এই বিকল্পগুলির মধ্যে একটি চয়ন করুন:

class MyClass
  MYCONSTANT = "blah"

  def mymethod
    MYCONSTANT
  end
end

class MyClass
  def mymethod
    my_constant = "blah"
  end
end

2
শুভকামার জন্য কেউ উল্লেখ করেছেন যে "যে কোনও পরিবর্তনশীল যার নাম মূলধন দিয়ে শুরু হয় এটি একটি ধ্রুবক!"
ubienewbie


0

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

class MyClass
  def mymethod
    myconstant = "blah"
  end
end

0

রুবি পছন্দ করেন না যে আপনি কোনও পদ্ধতির অভ্যন্তরে ধ্রুবক বরাদ্দ করছেন কারণ এটি পুনরায় নিয়োগের ঝুঁকি নিয়েছে। আমার আগে বেশ কয়েকটি এসও উত্তর একটি পদ্ধতির বাইরে এটি নির্ধারণের বিকল্পটি দেয় - তবে ক্লাসে, এটি নির্ধারণের জন্য আরও ভাল জায়গা।


1
ওয়েকোম টু এসও জন আপনি যা বর্ণনা করছেন তার কিছু নমুনা কোড যুক্ত করে আপনি উত্তরটি উন্নত করতে বিবেচনা করতে পারেন।
ক্লিপটাস

0

অ্যারে (এবং হ্যাশ) পদ্ধতি # স্থান সম্পর্কে আমাকে স্মরণ করিয়ে দেওয়ার জন্য ডোরিয়ান এবং ফ্রোগজকে অনেক ধন্যবাদ, যা "অ্যারে বা হ্যাশের সামগ্রীগুলি প্রতিস্থাপন করতে পারে"।

একটি কনস্ট্যান্টের মান পরিবর্তিত হতে পারে এমন ধারণা, কিন্তু একটি বিরক্তিকর সতর্কতা সহ, রুবির কয়েকটি ধারণামূলক ভুল পদক্ষেপগুলির মধ্যে একটি - এটি হয় সম্পূর্ণরূপে অপরিবর্তনীয় বা স্থির ধারণাটিকে পুরোপুরি ফেলে দিতে হবে dump কোডারের দৃষ্টিকোণ থেকে, একটি ধ্রুবকটি ঘোষণামূলক এবং ইচ্ছাকৃত, এটি অন্যের কাছে একটি সংকেত যে "এই মানটি সত্যই একবার ঘোষিত / নির্ধারিত হয়ে গেলে তা পরিবর্তনযোগ্য" "

তবে কখনও কখনও একটি "সুস্পষ্ট ঘোষণা" আসলে ভবিষ্যতের অন্যান্য কার্যকর সুযোগগুলিকে পূর্বাভাস দেয়। উদাহরণ স্বরূপ...

সেখানে হয় উদাহরণস্বরূপ, একটি REPL মত প্রম্পট-লুপ থেকে পুনরায় লোড argv, তারপর পুরনো আরো (পরবর্তী) OptionParser.parse argv rerunning: বৈধ ব্যবহারের ক্ষেত্রে যেখানে একটি "ধ্রুবক এর" মান সত্যিই পরিবর্তন করা প্রয়োজন হতে পারে! কল - ভয়েলা! "কমান্ড লাইন আরগস" একটি সম্পূর্ণ নতুন গতিশীল ইউটিলিটি দেয়।

ব্যবহারিক সমস্যা পারেন সম্ভাব্য ধৃষ্টতা যে, "argv একটি ধ্রুবক হতে হবে" সঙ্গে বা optparse নিজস্ব আরম্ভ পদ্ধতিতে, যা হার্ড কোড পরবর্তী প্রক্রিয়াকরণের জন্য উদাহরণস্বরূপ Var @default_argv করার argv এর নিয়োগ - যে অ্যারে (argv) সত্যিই প্যারামিটার হওয়া উচিত, পুনর্-পার্স এবং পুনরায় ব্যবহারকে উত্সাহিত করা, যেখানে উপযুক্ত। উপযুক্ত প্যারামিটারাইজেশন, উপযুক্ত ডিফল্ট (বলুন, এআরজিভি) কখনও "ধ্রুবক" এআরজিভি পরিবর্তন করার প্রয়োজন এড়াতে পারে। চিন্তাভাবনার মাত্র 2 wor-ওয়ার্থ ...

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