জেনেরিক প্রকারের বিপরীতে কোনও সম্পর্কিত ধরণের ব্যবহার করা কখন উপযুক্ত?


108

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

জন্য RFC যে যুক্ত ধরনের চালু বলেছেন:

এই আরএফসি দ্বারা বৈশিষ্ট্য মিলে স্পষ্ট করে:

  • সমস্ত বৈশিষ্ট্য ধরণের পরামিতিগুলি ইনপুট প্রকার হিসাবে বিবেচনা করা হচ্ছে এবং and
  • সম্পর্কিত ধরণের সরবরাহ করা, যা আউটপুট প্রকারের

আরএফসি একটি প্রেরণাদায়ী উদাহরণ হিসাবে একটি গ্রাফ কাঠামো ব্যবহার করে, এবং এটি ডকুমেন্টেশনেও ব্যবহৃত হয় , তবে আমি প্রকার-পরামিতিযুক্ত সংস্করণে সম্পর্কিত ধরণের সংস্করণটির সুবিধার জন্য সম্পূর্ণভাবে প্রশংসা না করার জন্য স্বীকার করব। প্রাথমিক বিষয়টি হল যে distanceপদ্ধতিটি সম্পর্কে Edgeধরণের যত্ন নেওয়া দরকার নেই । এটি দুর্দান্ত, তবে এগুলির সাথে সম্পর্কিত ধরণেরগুলি কিছুটা অগভীর বলে মনে হচ্ছে।

অনুশীলনে ব্যবহারের জন্য আমি প্রাসঙ্গিক প্রকারগুলি বেশ স্বজ্ঞাত হিসাবে খুঁজে পেয়েছি তবে আমার নিজের এপিআইতে কোথায় এবং কখন সেগুলি ব্যবহার করা উচিত তা সিদ্ধান্ত নেওয়ার সময় আমি নিজেকে লড়াই করে দেখতে পাই।

কোড লেখার সময়, আমি কখন জেনেরিক টাইপ প্যারামিটারের সাথে যুক্ত কোনও প্রকারটি বেছে নিতে পারি এবং কখন আমার বিপরীতটি করা উচিত?

উত্তর:


75

দ্যা রিস্ট প্রোগ্রামিং ল্যাঙ্গুয়েজের দ্বিতীয় সংস্করণে এখন এটি স্পর্শ করা হয়েছে । যাইহোক, এর পাশাপাশি কিছুটা ডুব দেই।

আসুন একটি সহজ উদাহরণ দিয়ে শুরু করা যাক।

বৈশিষ্ট্য পদ্ধতিটি ব্যবহার করা কখন উপযুক্ত?

দেরীতে বাইন্ডিং প্রদানের একাধিক উপায় রয়েছে :

trait MyTrait {
    fn hello_word(&self) -> String;
}

বা:

struct MyTrait<T> {
    t: T,
    hello_world: fn(&T) -> String,
}

impl<T> MyTrait<T> {
    fn new(t: T, hello_world: fn(&T) -> String) -> MyTrait<T>;

    fn hello_world(&self) -> String {
        (self.hello_world)(self.t)
    }
}

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

এক পার্থক্য (শব্দার্থিক ভাবে) যে traitবাস্তবায়ন গ্যারান্টী যে একটি প্রদত্ত টাইপ জন্য Tবাস্তবায়ন trait, hello_worldসবসময় যেহেতু একই আচরণ থাকবে structবাস্তবায়ন একটি উদাহরণ হিসেবে বলা যায় প্রতি ভিত্তিতে একটি ভিন্ন আচরণ থাকার অনুমতি দেয়।

কোনও পদ্ধতি ব্যবহার উপযুক্ত কিনা তা নির্ভর করে ইউজকেসের উপর!

কোনও যুক্ত প্রকারটি ব্যবহার করা কখন উপযুক্ত?

একইভাবে traitউপরের পদ্ধতিগুলির ক্ষেত্রে, সম্পর্কিত ধরণটি দেরী বাঁধাইয়ের একটি ফর্ম (যদিও এটি সংকলনের সময় ঘটে), ব্যবহারকারীকে traitকোনও নির্দিষ্ট উদাহরণের জন্য নির্দিষ্ট করতে দেয় যা বিকল্পটি টাইপ করে। এটি একমাত্র উপায় নয় (এভাবে প্রশ্ন):

trait MyTrait {
    type Return;
    fn hello_world(&self) -> Self::Return;
}

বা:

trait MyTrait<Return> {
    fn hello_world(&Self) -> Return;
}

উপরের পদ্ধতিগুলির দেরীতে বাঁধাইয়ের সমতুল্য:

  • প্রথমটি প্রয়োগ করে যে কোনও প্রদত্তের জন্য Selfএখানে একক Returnযুক্ত রয়েছে
  • দ্বিতীয়, পরিবর্তে, বাস্তবায়ন অনুমতি দেয় MyTraitজন্য Selfএকাধিক জন্যReturn

কোন ফর্মটি আরও উপযুক্ত তা নির্ভর করে unক্যবদ্ধতা প্রয়োগ করার বিষয়টি বোধগম্য কিনা on উদাহরণ স্বরূপ:

  • Deref একটি সম্পর্কিত ধরণের ব্যবহার করে কারণ একতা ছাড়াই সংকলক অনুমানের সময় পাগল হয়ে যায়
  • Add একটি যুক্ত প্রকার ব্যবহার করে কারণ এর লেখক ভেবেছিলেন যে দুটি যুক্তি দিয়ে একটি যুক্তিসঙ্গত রিটার্ন টাইপ হবে

যেমন আপনি দেখতে পাচ্ছেন, যদিও Derefএকটি সুস্পষ্ট ইউজকেস (প্রযুক্তিগত প্রতিবন্ধকতা) রয়েছে, তবে এর কেস Addকম স্পষ্টভাবে কাটা হয়েছে: সম্ভবত i32 + i32ফল দেওয়া i32বা Complex<i32>প্রসঙ্গের উপর নির্ভর করে বোধগম্য হবে ? তবুও, লেখক তাদের রায় প্রয়োগ করেছেন এবং সিদ্ধান্ত নিয়েছেন যে সংযোজনের জন্য রিটার্নের ধরণের ওভারলোডিং অপ্রয়োজনীয় was

আমার ব্যক্তিগত অবস্থান হ'ল সঠিক উত্তর নেই। তবুও, ইউনিটিটির যুক্তি ছাড়িয়ে আমি উল্লেখ করব যে সম্পর্কিত প্রকারগুলি নির্দিষ্ট করে নির্দিষ্ট পরামিতিগুলির সংখ্যা হ্রাস করার সাথে সাথে বৈশিষ্ট্য ব্যবহার করা সহজ করে তোলে, তাই যদি নিয়মিত বৈশিষ্ট্য পরামিতি ব্যবহারের নমনীয়তার সুবিধাগুলি সুস্পষ্ট না হয় তবে I সম্পর্কিত প্রকারের সাথে শুরু করার পরামর্শ দিন।


4
আমাকে কিছুটা সরল করার চেষ্টা করুন: trait/struct MyTrait/MyStructএক impl MyTrait forবা একটিকে অনুমতি দেয় impl MyStructtrait MyTrait<Return>একাধিক implগুলি এর অনুমতি দেয় কারণ এটি জেনেরিক। Returnযে কোনও ধরণের হতে পারে। জেনেরিক স্ট্রাক্ট একই।
পল-সেবাস্তিয়ান মানোলে


"প্রথমটি প্রয়োগ করে যে প্রদত্ত স্বের জন্য সেখানে একক রিটার্ন যুক্ত রয়েছে"। এটি তাত্ক্ষণিক অর্থে সত্য, তবে একটি জেনেরিক বৈশিষ্ট্য সহ সাবক্ল্যাসিং করে অবশ্যই এই নিষেধাজ্ঞার পক্ষে কাজ করতে পারে। সম্ভবত ইউনিটিসিটি কেবলমাত্র একটি পরামর্শ হতে পারে এবং প্রয়োগ করা হয় না
joel

36

সংযুক্ত প্রকারগুলি হ'ল একটি গোষ্ঠীকরণ প্রক্রিয়া , সুতরাং এটি যখন গ্রুপের সাথে একসাথে বোঝা যায় তখন সেগুলি ব্যবহার করা উচিত।

Graphবৈশিষ্ট্য ডকুমেন্টেশন চালু এই একটি উদাহরণ। আপনি একটি চান Graphজেনেরিক হতে, কিন্তু একবার আপনি একটি নির্দিষ্ট ধরনের আছে Graph, আপনি না চান Nodeবা Edgeধরনের আর তারতম্য। একটি নির্দিষ্ট Graphপ্রয়োগ একক প্রয়োগের মধ্যে এই ধরণেরগুলি পরিবর্তিত করতে চায় না এবং প্রকৃতপক্ষে চায় যে সেগুলি সর্বদা একই থাকে। তারা একসঙ্গে দলবদ্ধ করা হয়ে গেলে, অথবা এক এমনও বলা চলে যুক্ত


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