আপনি রুবিতে প্রোটোটাইপ-ভিত্তিক প্রোগ্রামিং করতে ক্লোন ব্যবহার করতে পারেন। রুবির অবজেক্ট ক্লাস ক্লোন পদ্ধতি এবং ডুপ পদ্ধতি উভয়কেই সংজ্ঞায়িত করে। ক্লোন এবং ডুপ উভয়ই এটি অনুলিপি করছে এমন একটি অগভীর অনুলিপি তৈরি করে; অর্থাৎ, বস্তুর উদাহরণের ভেরিয়েবলগুলি অনুলিপি করা হয় তবে তারা যে বস্তুগুলি উল্লেখ করে তা নয়। আমি একটি উদাহরণ প্রদর্শন করব:
class Apple
attr_accessor :color
def initialize
@color = 'red'
end
end
apple = Apple.new
apple.color
=> "red"
orange = apple.clone
orange.color
=> "red"
orange.color << ' orange'
=> "red orange"
apple.color
=> "red orange"
উপরের উদাহরণে লক্ষ্য করুন, কমলা ক্লোনটি আপেল বস্তুর রাজ্যের (অর্থাত্ ভেরিয়েবলগুলি) অনুলিপি করে, তবে যেখানে আপেল বস্তু অন্যান্য বস্তুর (যেমন স্ট্রিং অবজেক্ট রঙ) উল্লেখ করে সেখানে সেই উল্লেখগুলি অনুলিপি করা হয় না। পরিবর্তে, আপেল এবং কমলা উভয় একই বস্তুর রেফারেন্স! আমাদের উদাহরণস্বরূপ, রেফারেন্সটি হল স্ট্রিং অবজেক্ট 'লাল'। কমলা যখন বিদ্যমান স্ট্রিং অবজেক্টটি সংশোধন করতে <<, সংযোজন পদ্ধতিটি ব্যবহার করে, তখন স্ট্রিং অবজেক্টটিকে 'লাল কমলা'তে পরিবর্তন করা হয়। এটি কার্যকরভাবে আপেল-রঙকেও পরিবর্তন করে, যেহেতু তারা উভয়ই একই স্ট্রিং অবজেক্টের দিকে নির্দেশ করছে।
পার্শ্ব নোট হিসাবে, অ্যাসাইনমেন্ট অপারেটর =, একটি নতুন অবজেক্ট বরাদ্দ করবে এবং এইভাবে একটি রেফারেন্স নষ্ট করবে। এখানে একটি বিক্ষোভ:
class Apple
attr_accessor :color
def initialize
@color = 'red'
end
end
apple = Apple.new
apple.color
=> "red"
orange = apple.clone
orange.color
=> "red"
orange.color = 'orange'
orange.color
=> 'orange'
apple.color
=> 'red'
উপরের উদাহরণে, যখন আমরা কমলা রঙের ক্লোনার রঙ উদাহরণ পদ্ধতিতে একটি নতুন নতুন অবজেক্টকে অর্পণ করি তখন এটি আর আপেলের মতো একই বস্তুর উল্লেখ করে না। অতএব, আমরা এখন আপেলের রঙ পদ্ধতিকে প্রভাবিত না করে কমলার রঙের পদ্ধতিটি পরিবর্তন করতে পারি, তবে আমরা যদি আপেল থেকে অন্য কোনও বস্তুর ক্লোন করি, তবে নতুন বস্তুটি আপেল হিসাবে অনুলিপিভুক্ত ভেরিয়েবলগুলিতে একই বস্তুটিকে উল্লেখ করবে।
ডুপটি এটি অনুলিপি করা অবজেক্টের একটি অগভীর অনুলিপিও তৈরি করবে এবং যদি আপনি ডুপের জন্য উপরে প্রদর্শিত একই প্রদর্শনী করেন তবে আপনি দেখতে পাবেন যে এটি ঠিক একইভাবে কাজ করে। তবে ক্লোন এবং ডুপের মধ্যে দুটি প্রধান পার্থক্য রয়েছে। প্রথমত, অন্যরা যেমন উল্লেখ করেছে, ক্লোন হিমায়িত অবস্থায় থাকা অনুলিপি করে এবং ডুপ করে না। এটার মানে কি? রুবিতে 'হিমায়িত' শব্দটি অপরিবর্তনীয় একটি অতিপ্রাকৃত শব্দ, যা নিজে কম্পিউটার বিজ্ঞানের একটি নাম, যার অর্থ কিছু পরিবর্তন করা যায় না। সুতরাং, রুবির কোনও হিমায়িত বস্তু কোনওভাবেই সংশোধন করা যায় না; এটি বাস্তবে অপরিবর্তনীয়। আপনি যদি কোনও হিমায়িত অবজেক্টটি সংশোধন করার চেষ্টা করেন, রুবি একটি রানটাইমআরারের ব্যতিক্রম উত্থাপন করবে। যেহেতু ক্লোন হিমায়িত অবস্থায় অনুলিপি করে, যদি আপনি একটি ক্লোন করা বস্তুকে সংশোধন করার চেষ্টা করেন, এটি রানটাইমআরারের ব্যতিক্রম বাড়িয়ে তুলবে। বিপরীতে, যেহেতু ডুপ হিমায়িত অবস্থায় অনুলিপি করে না,
class Apple
attr_accessor :color
def initialize
@color = 'red'
end
end
apple = Apple.new
apple.frozen?
=> false
apple.freeze
apple.frozen?
=> true
apple.color = 'crimson'
RuntimeError: can't modify frozen Apple
apple.color << ' crimson'
=> "red crimson" # we cannot modify the state of the object, but we can certainly modify objects it is referencing!
orange = apple.dup
orange.frozen?
=> false
orange2 = apple.clone
orange2.frozen?
=> true
orange.color = 'orange'
=> "orange" # we can modify the orange object since we used dup, which did not copy the frozen state
orange2.color = 'orange'
RuntimeError: can't modify frozen Apple # orange2 raises an exception since the frozen state was copied via clone
দ্বিতীয়, এবং আরও মজার বিষয় হল, ক্লোন সিঙ্গলটন ক্লাসের অনুলিপি করেছে (এবং এর ফলে এর পদ্ধতিগুলি)! আপনি যদি রুবিতে প্রোটোটাইপ-ভিত্তিক প্রোগ্রামিং করতে চান তবে এটি খুব কার্যকর। প্রথমে দেখা যাক যে প্রকৃতপক্ষে সিঙ্গলটন পদ্ধতিগুলি ক্লোন দিয়ে অনুলিপি করা হয়েছে এবং তারপরে আমরা এটি রুবিতে প্রোটোটাইপ-ভিত্তিক প্রোগ্রামিংয়ের উদাহরণে প্রয়োগ করতে পারি।
class Fruit
attr_accessor :origin
def initialize
@origin = :plant
end
end
fruit = Fruit.new
=> #<Fruit:0x007fc9e2a49260 @origin=:plant>
def fruit.seeded?
true
end
2.4.1 :013 > fruit.singleton_methods
=> [:seeded?]
apple = fruit.clone
=> #<Fruit:0x007fc9e2a19a10 @origin=:plant>
apple.seeded?
=> true
আপনি দেখতে পাচ্ছেন, ফলের অবজেক্টের উদাহরণটির সিঙ্গলটন ক্লাসটি ক্লোনটিতে অনুলিপি করা হয়েছে। এবং তাই ক্লোনযুক্ত বস্তুর একক পদ্ধতিতে প্রবেশ রয়েছে: বীজযুক্ত ?. তবে ডুপের ক্ষেত্রে এটি হয় না:
apple = fruit.dup
=> #<Fruit:0x007fdafe0c6558 @origin=:plant>
apple.seeded?
=> NoMethodError: undefined method `seeded?'
এখন প্রোটোটাইপ-ভিত্তিক প্রোগ্রামিংয়ে আপনার কাছে এমন ক্লাস নেই যা অন্যান্য ক্লাসগুলি প্রসারিত করে এবং তারপরে ক্লাসগুলির উদাহরণ তৈরি করে যার পদ্ধতিগুলি পিতামাত্ত শ্রেণীর কাছ থেকে উদ্ভূত হয় যা একটি নীলনকশা হিসাবে কাজ করে। পরিবর্তে, আপনার একটি বেস অবজেক্ট রয়েছে এবং তারপরে আপনি তার পদ্ধতিগুলি সহ রাষ্ট্রটি অনুলিপি করে একটি নতুন অবজেক্ট তৈরি করুন (অবশ্যই, যেহেতু আমরা ক্লোনটির মাধ্যমে অগভীর অনুলিপিগুলি করছি, কোনও বস্তুর উদাহরণ ভেরিয়েবলের রেফারেন্সটি জাভাস্ক্রিপ্টের মতো ভাগ করা হবে) এগুলির নমুনা)। তারপরে ক্লোন পদ্ধতিগুলির বিশদ পূরণ করে আপনি বস্তুর স্থিতি পূরণ বা পরিবর্তন করতে পারেন। নীচের উদাহরণে, আমাদের একটি বেস ফলের অবজেক্ট রয়েছে। সমস্ত ফলের বীজ থাকে, তাই আমরা একটি পদ্ধতি সংখ্যা_সামান্য তৈরি করি। তবে আপেলের একটি বীজ থাকে এবং তাই আমরা একটি ক্লোন তৈরি করি এবং বিশদটি পূরণ করি। এখন যখন আমরা আপেল ক্লোন করি, আমরা কেবল পদ্ধতিগুলি ক্লোন করেইছিলাম না তবে আমরা রাজ্যের ক্লোন করেছিলাম! মনে রাখবেন ক্লোনটি রাষ্ট্রের অগভীর অনুলিপি করে (উদাহরণস্বরূপ ভেরিয়েবল)। এবং তার কারণ হিসাবে, যখন আমরা একটি রেড_্যাপল পেতে আপেল ক্লোন করব তখন লাল_ অ্যাপলটিতে স্বয়ংক্রিয়ভাবে 1 টি বীজ থাকবে! আপনি রেড_এপলকে অ্যাপল হিসাবে উত্তরাধিকার সূত্রে প্রাপ্ত একটি বিষয় হিসাবে ভাবতে পারেন, ফলস্বরূপ ফল থেকে প্রাপ্ত হয়। সুতরাং, আমি ফল এবং অ্যাপলকে মূলধন করেছিলাম। ক্লোন এবং সৌজন্যে ক্লোনটির অবজেক্টের মধ্যে পার্থক্যটি আমরা সরিয়ে দিয়েছি।
Fruit = Object.new
def Fruit.number_of_seeds=(number_of_seeds)
@number_of_seeds = number_of_seeds
end
def Fruit.number_of_seeds
@number_of_seeds
end
Apple = Fruit.clone
=> #<Object:0x007fb1d78165d8>
Apple.number_of_seeds = 1
Apple.number_of_seeds
=> 1
red_apple = Apple.clone
=> #<Object:0x007fb1d892ac20 @number_of_seeds=1>
red_apple.number_of_seeds
=> 1
অবশ্যই, আমাদের প্রোটোপ-ভিত্তিক প্রোগ্রামিংয়ে একটি কনস্ট্রাক্টর পদ্ধতি থাকতে পারে:
Fruit = Object.new
def Fruit.number_of_seeds=(number_of_seeds)
@number_of_seeds = number_of_seeds
end
def Fruit.number_of_seeds
@number_of_seeds
end
def Fruit.init(number_of_seeds)
fruit_clone = clone
fruit_clone.number_of_seeds = number_of_seeds
fruit_clone
end
Apple = Fruit.init(1)
=> #<Object:0x007fcd2a137f78 @number_of_seeds=1>
red_apple = Apple.clone
=> #<Object:0x007fcd2a1271c8 @number_of_seeds=1>
red_apple.number_of_seeds
=> 1
শেষ পর্যন্ত, ক্লোন ব্যবহার করে, আপনি জাভাস্ক্রিপ্ট প্রোটোটাইপ আচরণের অনুরূপ কিছু পেতে পারেন।
dup
এবং কীগুলির মধ্যে পার্থক্য না জানতামclone
তবে কেন আপনি অন্যটির চেয়ে একটি ব্যবহার করতেন।