রুবি অন্তর্ভুক্ত এবং প্রসারিত মধ্যে পার্থক্য কি?


414

শুধু আমার মাথা পেতে রুবি metaprogramming। মিক্সিন / মডিউলগুলি সর্বদা আমাকে বিভ্রান্ত করার জন্য পরিচালনা করে।

  • অন্তর্ভুক্ত : টার্গেট ক্লাসে উদাহরণ পদ্ধতি হিসাবে নির্দিষ্ট মডিউল পদ্ধতিতে মিশ্রণ
  • প্রসারিত : নির্দিষ্ট ক্লাসের লক্ষ্য শ্রেণীর শ্রেণি হিসাবে নির্দিষ্ট মডিউল পদ্ধতিতে মিশ্রিত

সুতরাং প্রধান পার্থক্য ঠিক এই বা একটি বড় ড্রাগন লুকিয়ে আছে? যেমন

module ReusableModule
  def module_method
    puts "Module Method: Hi there!"
  end
end

class ClassThatIncludes
  include ReusableModule
end
class ClassThatExtends
  extend ReusableModule
end

puts "Include"
ClassThatIncludes.new.module_method       # "Module Method: Hi there!"
puts "Extend"
ClassThatExtends.module_method            # "Module Method: Hi there!"

: এই লিঙ্ক চেক আউট খুব juixe.com/techknow/index.php/2006/06/15/mixins-in-ruby
Donato

উত্তর:


249

আপনি যা বলেছেন তা সঠিক। তবে এর চেয়ে আরও কিছু আছে।

আপনি যদি একটি বর্গ থাকে Klazzএবং মডিউল Modসহ Modমধ্যে Klazzদৃষ্টান্ত দেয় Klazzএক্সেস Modএর পদ্ধতি। অথবা আপনি প্রসারিত করতে পারেন Klazzসঙ্গে Modদান বর্গ Klazz এক্সেস Modএর পদ্ধতি। তবে আপনি এটি দিয়ে একটি স্বেচ্ছাসেবী বস্তু প্রসারিত করতে পারেন o.extend ModModএক্ষেত্রে একই শ্রেণীর অন্যান্য সমস্ত বস্তু যেমন oনা থাকে ততক্ষণ পৃথক বস্তুটির পদ্ধতিগুলি পায় ।


324

প্রসারিত - নির্দিষ্ট মডিউলটির পদ্ধতিগুলি এবং লক্ষ্যগুলির মেটাগ্লাসে (যেমন সিঙ্গলটন শ্রেণি) যুক্ত করে ধ্রুবক যুক্ত করে eg

  • যদি আপনি কল করেন Klazz.extend(Mod), এখন ক্লাজের মোডের পদ্ধতি রয়েছে (শ্রেণি পদ্ধতি হিসাবে)
  • যদি আপনি কল করেন obj.extend(Mod), এখন আপত্তিটির কাছে মোডের পদ্ধতি রয়েছে (উদাহরণস্বরূপ পদ্ধতি), তবে obj.classএই পদ্ধতিগুলি যুক্ত করার কোনও অন্য উদাহরণ নেই ।
  • extend একটি পাবলিক পদ্ধতি

অন্তর্ভুক্ত - ডিফল্টরূপে, এটি নির্দিষ্ট মডিউলটির পদ্ধতিগুলিতে লক্ষ্য মডিউল / শ্রেণিতে উদাহরণ পদ্ধতি হিসাবে মিশ্রিত হয়। যেমন

  • যদি আপনি কল করেন class Klazz; include Mod; end;, এখন ক্লাজের সমস্ত দৃষ্টিতে মোডের পদ্ধতিগুলিতে অ্যাক্সেস রয়েছে (উদাহরণস্বরূপ পদ্ধতিগুলি)
  • include এটি একটি ব্যক্তিগত পদ্ধতি, কারণ এটি ধারক শ্রেণীর / মডিউলটির মধ্যে থেকে কল করার ইচ্ছা।

তবে , মডিউল খুব প্রায়ই ওভাররাইড include বানর-প্যাচিং দ্বারা 'র আচরণ includedপদ্ধতি। এটি লিগ্যাসি রেলস কোডে খুব সুস্পষ্ট। ইহুদা কাটজ থেকে আরও বিশদ

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

class Klazz
  include Mod
end
  • মোড যদি ইতিমধ্যে ক্লাজ বা এর পূর্বপুরুষদের মধ্যে অন্তর্ভুক্ত থাকে তবে অন্তর্ভুক্ত বিবৃতিটির কোনও প্রভাব নেই
  • এটি ক্লাজে মোডের ধ্রুবককেও অন্তর্ভুক্ত করে, যতক্ষণ না তারা সংঘর্ষ না করে
  • এটি ক্লাজকে মোডের মডিউল ভেরিয়েবলগুলিতে অ্যাক্সেস দেয়, যেমন @@fooবা@@bar
  • যদি চক্রটি অন্তর্ভুক্ত থাকে তবে আর্গুমেন্টেরর উত্থাপন করে
  • কলারের তাত্ক্ষণিক পূর্বপুরুষ হিসাবে মডিউলটি সংযুক্ত করে (যেমন এটি ক্লাজ.অ্যানস্টোরগুলিতে মোড যুক্ত করে, তবে মোড ক্লাজ.সুপারগ্লাস.সুপারক্লাস.সুপারক্লাসের শৃঙ্খলে যোগ করা হয় না So সুতরাং, superক্লাজে # foo এ কল করার আগে মোড # foo পরীক্ষা করা হবে ক্লাজের আসল সুপারক্লাসের ফু পদ্ধতিতে details বিশদগুলির জন্য রুবিস্পেক দেখুন))

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


22
আমি জানি এটি বেশ পুরানো পোস্ট, তবে উত্তরটির স্পষ্টতা আমাকে মন্তব্য করা থেকে বিরত রাখতে পারে না। একটি সুন্দর ব্যাখ্যা জন্য অনেক ধন্যবাদ।
মোহাম্মদসানাউল্লা

2
@ আনোয়ার স্পষ্টতই, তবে এখন আমি মন্তব্য করতে পারি এবং আমি আর্টিকেলটি আবার খুঁজে পেতে সক্ষম হয়েছি। এটি এখানে উপলভ্য: aaronlasseigne.com/2012/01/17/exPLining- অন্তর্ভুক্ত- এবং- প্রসারিত এবং আমি এখনও মনে করি যে স্কিমা বোঝাপড়া আরও সহজ করে তোলে
systho

1
এই প্রতিক্রিয়াটির বড় জয়টি কীভাবে ব্যবহারের উপর নির্ভর করে extendক্লাস বা উদাহরণ পদ্ধতি হিসাবে পদ্ধতি প্রয়োগ করতে পারে । Klass.extend= শ্রেণি পদ্ধতি, objekt.extend= উদাহরণ পদ্ধতি। আমি সবসময় (ভুলভাবে) অধিকৃত বর্গ পদ্ধতি থেকে এসেছেন extend, এবং থেকে উদাহরণস্বরূপ include
ফ্র্যাঙ্ক কোহল

16

এটাই সঠিক.

পর্দার অন্তর্ভুক্ত, অন্তর্ভুক্ত হ'ল append_features জন্য একটি উপনাম , যা (ডক্স থেকে):

রুবির ডিফল্ট বাস্তবায়ন হ'ল এই মডিউলটির কনস্ট্যান্টস, পদ্ধতি এবং মডিউল ভেরিয়েবলগুলি একটি এমডুলিতে যুক্ত করা যদি এই মডিউলটি ইতিমধ্যে এমডিউলে বা এর পূর্বপুরুষদের মধ্যে যোগ না করা হয়।


4

আপনি যখন includeএকটি শ্রেণিতে মডিউল করেন, মডিউল পদ্ধতিগুলি উদাহরণ পদ্ধতি হিসাবে আমদানি করা হয় ।

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

উদাহরণস্বরূপ, যদি আমাদের মডিউলটি নীচে Module_testনির্ধারিত থাকে:

module Module_test
  def func
    puts "M - in module"
  end
end

এখন, includeমডিউল জন্য । যদি আমরা ক্লাসটি Aনিম্নলিখিতভাবে সংজ্ঞায়িত করি :

class A
  include Module_test
end

a = A.new
a.func

আউটপুট হবে: M - in module

আমরা যদি লাইন প্রতিস্থাপন include Module_testসঙ্গে extend Module_testএবং কোড আবার চালাতে আমরা ত্রুটিটি পান: undefined method 'func' for #<A:instance_num> (NoMethodError)

পদ্ধতি কল পরিবর্তন a.funcকরার জন্য A.func, আউটপুট পরিবর্তন করুন: M - in module

উপরের কোড এক্সিকিউশন থেকে, এটি স্পষ্ট যে আমরা যখন includeএকটি মডিউল, তার পদ্ধতিগুলি উদাহরণ পদ্ধতিতে পরিণত হয় এবং যখন আমরা extendএকটি মডিউল করি, এর পদ্ধতিগুলি বর্গ পদ্ধতিতে পরিণত হয় ।


3

রুবিস্পেসের মাধ্যমে খননের টিপ সহ অন্যান্য সমস্ত উত্তর ভাল:

https://github.com/rubyspec/rubyspec/blob/master/core/module/include_spec.rb

https://github.com/rubyspec/rubyspec/blob/master/core/module/extend_object_spec.rb

ব্যবহারের ক্ষেত্রে হিসাবে:

আপনি ক্লাসটি ক্লাসে ক্লাসটিউনক্লুডে মডিউল পুনরায় ব্যবহারযোগ্য মডুলেল অন্তর্ভুক্ত করলে পদ্ধতি, ধ্রুবক, শ্রেণি, সাবমডিউল এবং অন্যান্য ঘোষণাগুলি রেফারেন্স হয়।

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

আপনি যদি অ্যাক্টিভসপোর্ট :: কনসার্ন ব্যবহার করেন তবে। অন্তর্ভুক্ত () কার্যকারিতা আপনাকে অন্তর্ভুক্ত ক্লাসটি সরাসরি নতুন করে লিখতে দেয়। একটি কনসার্নের অভ্যন্তরে মডিউল ক্লাসমেথডগুলি বর্ধিত ক্লাসে প্রসারিত (অনুলিপি করা) হয়।


1

আমি প্রক্রিয়াটি যেমন কাজ করে তেমনি ব্যাখ্যা করতে চাই। আমি সঠিক না হলে দয়া করে সংশোধন করুন।

যখন আমরা ব্যবহার includeকরি আমরা আমাদের ক্লাস থেকে একটি মডিউলে একটি লিঙ্কেজ যুক্ত করছি যা কিছু পদ্ধতি রয়েছে।

class A
include MyMOd
end

a = A.new
a.some_method

অবজেক্টগুলির কোনও পদ্ধতি নেই, কেবল ক্ল্যাস এবং মডিউল রয়েছে। সুতরাং যখন aমেসেজ পায় some_methodএটি সার্চ পদ্ধতি শুরু some_methodমধ্যে aএর eigen বর্গ, তারপর Aবর্গ এবং তারপর লিঙ্ক Aক্লাস মডিউল যদি কিছু নেই (বিপরীত ক্রম গত অন্তর্ভুক্ত জয়ী)।

আমরা যখন ব্যবহার extendকরি তখন আমরা অবজেক্টের ইগেন ক্লাসের একটি মডিউলে লিঙ্কেজ যুক্ত করব। সুতরাং আমরা যদি A.new.extend (মাইমড) ব্যবহার করি তবে আমরা আমাদের মডিউলের সাথে এ এর ​​উদাহরণ ইগেন ক্লাস বা a'ক্লাস যুক্ত করব। এবং যদি আমরা A.extend (মাইমড) ব্যবহার করি তবে আমরা এটির সাথে লিঙ্কেজ যুক্ত করছি (বস্তুর, শ্রেণিগুলিও বস্তুগুলি) ইজিঙ্ক্লাস A'

পদ্ধতিগুলির জন্য অনুসন্ধানের পথটি নীচে a: a => a '=> মডিউলগুলিকে একটি' শ্রেণি => এ সংযুক্ত করুন

এছাড়াও একটি প্রিপেন্ড পদ্ধতি রয়েছে যা লুকিংয়ের পথ পরিবর্তন করে:

a => a '=> প্রিপেন্ডেড মডিউলটি A => এ => এটিকে মডিউল অন্তর্ভুক্ত করে

আমার অদক্ষ ইংরেজির জন্য আমি দুঃখিত.

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