স্কেল: বিমূর্ত প্রকারের জেনেরিকস


250

আমি স্কাল: বিমূর্ত প্রকারের একটি ট্যুর পড়ছিলাম । বিমূর্ত প্রকারগুলি ব্যবহার করা কখন ভাল?

উদাহরণ স্বরূপ,

abstract class Buffer {
  type T
  val element: T
}

বরং যে জেনেরিকস, উদাহরণস্বরূপ,

abstract class Buffer[T] {
  val element: T
}

উত্তর:


257

আপনি এখানে এই ইস্যুতে একটি ভাল দৃষ্টিভঙ্গি আছে:

স্কালার টাইপ সিস্টেমের উদ্দেশ্য
মার্টিন ওডারস্কির সাথে একটি কথোপকথন,
বিল ভেনার্স এবং ফ্রাঙ্ক সোমার্সেরতৃতীয় খণ্ড(মে 18, ২০০৯)

আপডেট (অক্টোবর ২০০৯): নীচে নিম্নলিখিতটি আসলে বিল ভেনারদের এই নতুন নিবন্ধে চিত্রিত হয়েছে: স্ক্যালায়
জেনেরিক টাইপ পরামিতি বনাম অ্যাবস্ট্রাক্ট টাইপ সদস্য (শেষে সংক্ষেপে দেখুন)


(এখানে প্রথম সাক্ষাত্কারের প্রাসঙ্গিক নিষ্কাশন, মে ২০০৯, জোর আমার)

মূলনীতি

সর্বদা বিমূর্তকরণের দুটি ধারণা রয়েছে:

  • পরামিতি এবং
  • বিমূর্ত সদস্য।

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

স্কেল ওয়ে

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

কেন?

বিশেষত, বিমূর্ত প্রকারগুলি আপনাকে কী কিনে তা হ'ল আমরা এই পূর্বে যে cক্যবদ্ধ সমস্যাগুলির কথা বললাম তার একটি দুর্দান্ত চিকিত্সা
একটি স্ট্যান্ডার্ড সমস্যা যা দীর্ঘকাল ধরে ছিল, তা হ'ল প্রাণী এবং খাবারের সমস্যা।
ধাঁধাটি ছিল Animalএকটি পদ্ধতি সহ একটি ক্লাস eat, যা কিছু খাবার খায়।
সমস্যাটি হ'ল আমরা যদি প্রাণীটিকে সাবক্লাস করি এবং গাভীর মতো ক্লাস করি তবে তারা কেবল গ্রাস খাবে এবং স্বেচ্ছাসেবী খাবার নয়। উদাহরণস্বরূপ, একটি গরু একটি মাছ খেতে পারে না।
আপনি যা চান তা বলতে সক্ষম হলেন যে একটি গাভীর একটি খাওয়ার পদ্ধতি রয়েছে যা কেবল ঘাস খায় অন্য জিনিসগুলি নয়।
প্রকৃতপক্ষে, আপনি জাভাতে এটি করতে পারবেন না কারণ এটি প্রমাণিত হয়েছে যে আপনি আগে থেকেই যে অ্যাপল ভেরিয়েবলের জন্য একটি ফল নির্ধারণ করার সমস্যাটির মতো নিরবচ্ছিন্ন পরিস্থিতি তৈরি করতে পারেন।

উত্তরটি হ'ল আপনি প্রাণী শ্রেণিতে একটি বিমূর্ত প্রকার যুক্ত করেন
আপনি বলছেন, আমার নতুন অ্যানিম্যাল ক্লাসে একটি ধরণের আছে SuitableFood, যা আমি জানি না।
সুতরাং এটি একটি বিমূর্ত প্রকার। আপনি এই ধরণের কোনও বাস্তবায়ন দেন না। তারপরে আপনার একটি eatপদ্ধতি রয়েছে যা কেবল খায় SuitableFood
এবং তারপরে Cowক্লাসে আমি বলব, ঠিক আছে, আমার কাছে একটি গরু আছে, যা ক্লাস প্রসারিত করে Animalএবং এর জন্য Cow type SuitableFood equals Grass
তাই বিমূর্ত ধরনের একটি সুপারক্লাস মধ্যে একটি টাইপ এই ধারণা যে আমি জানি না, যা আমি তারপর পরবর্তী উপশ্রেণী কিছু আমি জানি না পূর্ণ প্রদান

প্যারামিটারাইজেশন একই?

সত্যিই আপনি পারেন। আপনি যে ধরণের খাবার খান তা দিয়ে আপনি শ্রেণীর প্রাণীকে প্যারামিটারাইজ করতে পারেন।
কিন্তু বাস্তবে, আপনি যখন এটি বিভিন্ন বিভিন্ন জিনিস দিয়ে করেন, তখন এটি প্যারামিটারগুলির বিস্ফোরণের দিকে পরিচালিত করে এবং সাধারণত, আরও বেশি কী , পরামিতিগুলির সীমাতে
1998 এর ECOOP এ, কিম ব্রুস, ফিল ওয়াডলার এবং আমার একটি কাগজ ছিল যেখানে আমরা দেখিয়েছি যে আপনি যে জিনিসগুলি জানেন না তার সংখ্যা বাড়ানোর সাথে সাথে সাধারণ প্রোগ্রামটি চতুর্ভুজ আকারে বৃদ্ধি পাবে
সুতরাং প্যারামিটারগুলি না করার জন্য খুব ভাল কারণ রয়েছে তবে এই বিমূর্ত সদস্যগুলি রাখার কারণ তারা আপনাকে এই চতুর্ভুজটি দেয় না।


thatismatt মন্তব্য জিজ্ঞাসা:

আপনি কি মনে করেন যে নীচেরগুলি একটি ন্যায্য সংক্ষিপ্তসার:

  • অ্যাবস্ট্রাক্ট প্রকারগুলি 'হ্যাস-এ' বা 'ব্যবহার-এ' সম্পর্কের ক্ষেত্রে ব্যবহৃত হয় (উদাঃ ক Cow eats Grass)
  • যেখানে জেনেরিকগুলি সাধারণত সম্পর্কের (যেমন List of Ints) হয়

আমি নিশ্চিত নই যে বিমূর্ততা প্রকার বা জেনেরিক ব্যবহারের মধ্যে সম্পর্কটি ভিন্ন different ভিন্ন কি:

  • তারা কীভাবে ব্যবহৃত হয়, এবং
  • প্যারামিটারের সীমাগুলি কীভাবে পরিচালিত হয়।

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

প্রাসঙ্গিক নিষ্কাশন

সংজ্ঞা

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

(দ্রষ্টব্য: পারিবারিক পলিমারফিজম পুনঃব্যবহারযোগ্য তবে টাইপ-নিরাপদ পারস্পরিক পুনরাবৃত্তি শ্রেণিকে সমর্থন করার সমাধান হিসাবে বস্তু-ভিত্তিক ভাষার জন্য প্রস্তাবিত হয়েছে family পারিবারিক পলিমারফিজমের
একটি মূল ধারণা পরিবারগুলির ধারণা, যা পারস্পরিক পুনরাবৃত্তি শ্রেণীর গোষ্ঠী হিসাবে ব্যবহৃত হয়)

সীমাবদ্ধ বিমূর্ততা

abstract class MaxCell extends AbsCell {
type T <: Ordered { type O = T }
def setMax(x: T) = if (get < x) set(x)
}

এখানে টি এর প্রকারের ঘোষণাকে একটি উচ্চতর টাইপ বাউন্ড দ্বারা সীমাবদ্ধ করা হয় যা একটি শ্রেণীর নাম অর্ডার করা এবং একটি পরিমার্জন নিয়ে গঠিত { type O = T }
উপরের আবদ্ধ পরিমিত সেই উপশাখাকে করার উপশ্রেণী মধ্যে T এর বিশেষায়িত কোন ধরনের সদস্যের আদেশ Oএর equals T
এই সীমাবদ্ধতার কারণে, <শ্রেণিবদ্ধ অর্ডারের পদ্ধতিটি কোনও প্রাপক এবং টাইপ টির যুক্তির ক্ষেত্রে প্রযোজ্য বলে গ্যারান্টিযুক্ত
The উদাহরণটি দেখায় যে সীমাবদ্ধ টাইপ সদস্য নিজেই বাউন্ডের অংশ হিসাবে উপস্থিত হতে পারে।
(অর্থাত স্কাল এফ-সীমাবদ্ধ বহুবর্ষকে সমর্থন করে )

(দ্রষ্টব্য, পিটার ক্যানিং, উইলিয়াম কুক, ওয়াল্টার হিল, ওয়াল্টার ওলথফ পেপার থেকে:
কার্ডেলি এবং ওয়েগনার দ্বারা নির্দিষ্ট পরিমাণের সমস্ত সাব -টাইপের উপরে অভিন্নভাবে পরিচালিত টাইপিংয়ের একটি উপায় হিসাবে বাউন্ডেড কোয়ান্টিফিকেশন চালু হয়েছিল
They তারা একটি সাধারণ "অবজেক্ট" মডেলকে সংজ্ঞায়িত করেছিল defined এবং বেষ্টিত রাশিকরণ ব্যবহৃত টাইপ-যাচাই ফাংশন যে "বৈশিষ্ট্যাবলী"। একটি নির্দিষ্ট সেট থাকার সব বস্তুর উপর জানার জন্য
একটি অবজেক্ট ওরিয়েন্টেড ভাষায় আরো বাস্তবসম্মত উপস্থাপনা যে বস্তু উপাদান সম্ভব হবে যাও recursively-সংজ্ঞায়িত ধরনের
এ প্রসঙ্গে বেষ্টিত কোয়ান্টিফিকেশন আর তার উদ্দেশ্যযুক্ত উদ্দেশ্যে কাজ করে না functions নির্দিষ্ট ফাংশনগুলির একটি নির্দিষ্ট সেট থাকা সমস্ত বস্তুর জন্য উপলব্ধিযুক্ত ফাংশনগুলি সন্ধান করা সহজ তবে এটি কার্ডেল্লি-ওয়েগনার সিস্টেমে টাইপ করা যায় না।
অবজেক্ট-ওরিয়েন্টেড ভাষাগুলিতে টাইপড পলিমারফিক ফাংশনগুলির জন্য একটি ভিত্তি সরবরাহ করতে, আমরা এফ-সীমাবদ্ধ পরিমাণের প্রবর্তন করি)

একই মুদ্রার দুটি মুখ

প্রোগ্রামিং ভাষাগুলিতে বিমূর্তির মূল দুটি রূপ রয়েছে:

  • পরামিতি এবং
  • বিমূর্ত সদস্য।

প্রথম ফর্মটি কার্যকরী ভাষাগুলির জন্য আদর্শ, যখন দ্বিতীয় ফর্মটি সাধারণত অবজেক্ট-ওরিয়েন্টেড ভাষায় ব্যবহৃত হয়।

Ditionতিহ্যগতভাবে, জাভা মানগুলির জন্য প্যারামিটারাইজেশন এবং ক্রিয়াকলাপের জন্য সদস্য বিমূর্তি সমর্থন করে। জেনারিক সহ আরও সাম্প্রতিক জাভা 5.0 ধরণের ক্ষেত্রেও প্যারামিটারাইজেশন সমর্থন করে।

স্কেলে জেনেরিকগুলি যুক্ত করার জন্য যুক্তিগুলি দ্বিগুণ:

  • প্রথমত, অ্যাবস্ট্র্যাক্ট ধরণের এনকোডিংটি হাতে হাতে করা সহজ কাজ নয়। সংক্ষিপ্ততার ক্ষতি ছাড়াও, বিমূর্ত প্রকারের নামগুলির মধ্যে দুর্ঘটনাজনিত নাম দ্বন্দ্বের সমস্যা রয়েছে যা টাইপ পরামিতিগুলি অনুকরণ করে।

  • দ্বিতীয়ত, জেনেরিকস এবং বিমূর্ত প্রকারগুলি সাধারণত স্কালা প্রোগ্রামগুলিতে স্বতন্ত্র ভূমিকা পালন করে।

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

বাউন্ডেড পলিমারফিজম সহ একটি সিস্টেমে জেনারিক্সে অ্যাবস্ট্রাক্ট টাইপের পুনর্লিখনের ক্ষেত্রে টাইপের সীমাটির চতুর্ভুজ বিস্তারের প্রবণতা থাকতে পারে ।


অক্টোবর ২০০৯ আপডেট করুন

স্ক্যালায় জেনেরিক টাইপ পরামিতি বনাম বিমূর্ত প্রকারের সদস্য (বিল ভেনার্স)

(জোর আমার)

অ্যাবস্ট্রাক্ট টাইপ সদস্যদের সম্পর্কে আমার পর্যবেক্ষণটি হ'ল তারা সাধারণত জেনেরিক ধরণের পরামিতিগুলির চেয়ে ভাল পছন্দ যখন:

  • আপনি লোকদের বৈশিষ্ট্যের মাধ্যমে এই ধরণের সংজ্ঞাগুলিতে মিশ্রিত করতে চান ।
  • আপনি মনে করেন যে টাইপ সদস্যের নামটি যখন সংজ্ঞায়িত করা হচ্ছে তখন তার স্পষ্ট উল্লেখ কোড পাঠযোগ্যতার জন্য সহায়তা করবে

উদাহরণ:

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

// Type parameter version
class MySuite extends FixtureSuite3[StringBuilder, ListBuffer, Stack] with MyHandyFixture {
  // ...
}

প্রকারের সদস্য পদ্ধতির সাথে এটি দেখতে এটির মতো দেখাবে:

// Type member version
class MySuite extends FixtureSuite3 with MyHandyFixture {
  // ...
}

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

// Type parameter version
class MySuite extends FixtureSuite[StringBuilder] with StringBuilderFixture {
  // ...
}

স্ট্রিংবিল্ডার হিসাবে বর্ণিত প্যারামিটারের নামটি কী তা না দেখে তারা জানত না। অ্যাবস্ট্রাক্ট টাইপের সদস্য পদ্ধতির কোডে টাইপ প্যারামিটারের নামটি ঠিক সেখানে রয়েছে:

// Type member version
class MySuite extends FixtureSuite with StringBuilderFixture {
  type FixtureParam = StringBuilder
  // ...
}

পরবর্তী ক্ষেত্রে, কোডটির পাঠকরা দেখতে পান যে StringBuilderএটি "ফিক্সচার প্যারামিটার" টাইপ।
তাদের এখনও "ফিক্সার প্যারামিটার" বলতে কী বোঝায়, তবে তারা ডকুমেন্টেশন না দেখে কমপক্ষে টাইপের নামটি পেতে পারেন।


61
আপনি যখন এসে এই কাজটি করবেন তখন স্কালার প্রশ্নের জবাব দিয়ে আমার কীভাবে কর্মফল পয়েন্ট পাওয়ার কথা ??? :-)
ড্যানিয়েল সি সোব্রাল

7
হাই ড্যানিয়েল: আমি মনে করি প্যারামাইট্রাইজেশনের উপর বিমূর্ত প্রকারের সুবিধাগুলির চিত্রিত করার জন্য অবশ্যই কোন নিবিড় উদাহরণ থাকতে হবে। এই থ্রেডে কিছু পোস্ট করা একটি ভাল শুরু হবে;) আমি জানি যে আমি এটি উন্নত করব।
ভোনসি

1
আপনি কি মনে করেন যে নীচেরটি ন্যায্য সংক্ষিপ্তসার: অ্যাবস্ট্রাক্ট প্রকারগুলি 'হ্যাস-এ' বা 'ইউজ-এ' সম্পর্কগুলিতে ব্যবহৃত হয় (যেমন একটি গাভী খায় ঘাস) যেখানে জেনেরিক সাধারণত 'সম্পর্কের' (যেমন অন্তরের তালিকা)
thatismatt

আমি নিশ্চিত নই যে বিমূর্ততা প্রকার বা জেনেরিক ব্যবহারের মধ্যে সম্পর্কটি ভিন্ন different সেগুলি কীভাবে ব্যবহৃত হয় এবং প্যারামিটারের সীমাগুলি কীভাবে পরিচালিত হয় সেগুলি ভিন্ন। এক মুহুর্তে আমার উত্তর আরও।
ভনসি

1
নিজের কাছে নোট করুন: এই মে ২০১০ ব্লগ পোস্টটিও দেখুন
ভোনসি

37

আমি স্কেলা সম্পর্কে পড়ার সময় আমার একই প্রশ্ন ছিল।

জেনেরিকগুলি ব্যবহার করার সুবিধা হ'ল আপনি ধরণের পরিবার তৈরি করছেন are কেউ উপশ্রেণী করতে হবে Buffer-তারা শুধু ব্যবহার করতে পারেন Buffer[Any], Buffer[String]ইত্যাদি

আপনি যদি বিমূর্ত প্রকারটি ব্যবহার করেন তবে লোকেরা একটি সাবক্লাস তৈরি করতে বাধ্য হবে। মানুষ মত শ্রেণীর করতে হবে AnyBuffer, StringBufferইত্যাদি

আপনার নির্দিষ্ট প্রয়োজনের জন্য কোনটি ভাল তা আপনাকে সিদ্ধান্ত নিতে হবে।


18
Buffer { type T <: String }Buffer { type T = String }
মিমি পাতাগুলি

20

কাস্টম টেম্পলেটগুলি স্থাপন করতে আপনি টাইপ পরামিতিগুলির সাথে একযোগে বিমূর্ত প্রকারগুলি ব্যবহার করতে পারেন।

ধরে নেওয়া যাক আপনার সাথে তিনটি সংযুক্ত বৈশিষ্ট্য সহ একটি প্যাটার্ন স্থাপন করা দরকার:

trait AA[B,C]
trait BB[C,A]
trait CC[A,B]

টাইপ পরামিতিগুলিতে উল্লিখিত যুক্তিগুলি হ'ল এএ, বিবি, সিসি নিজেই শ্রদ্ধার সাথে

আপনি কিছু ধরণের কোড নিয়ে আসতে পারেন:

trait AA[B<:BB[C,AA[B,C]],C<:CC[AA[B,C],B]]
trait BB[C<:CC[A,BB[C,A]],A<:AA[BB[C,A],C]]
trait CC[A<:AA[B,CC[A,B]],B<:BB[CC[A,B],A]]

টাইপ প্যারামিটার বন্ডের কারণে যা এই সহজ উপায়ে কাজ করবে না। সঠিকভাবে উত্তরাধিকারী হওয়ার জন্য আপনাকে এটিকে সমবায় তৈরি করতে হবে

trait AA[+B<:BB[C,AA[B,C]],+C<:CC[AA[B,C],B]]
trait BB[+C<:CC[A,BB[C,A]],+A<:AA[BB[C,A],C]]
trait CC[+A<:AA[B,CC[A,B]],+B<:BB[CC[A,B],A]]

এই একটি নমুনা সংকলন করবে তবে এটি বৈকল্পিক বিধিগুলির জন্য দৃ requirements় প্রয়োজনীয়তা নির্ধারণ করে এবং কিছু অনুষ্ঠানে ব্যবহার করা যায় না

trait AA[+B<:BB[C,AA[B,C]],+C<:CC[AA[B,C],B]] {
  def forth(x:B):C
  def back(x:C):B
}
trait BB[+C<:CC[A,BB[C,A]],+A<:AA[BB[C,A],C]] {
  def forth(x:C):A
  def back(x:A):C
}
trait CC[+A<:AA[B,CC[A,B]],+B<:BB[CC[A,B],A]] {
  def forth(x:A):B
  def back(x:B):A
}

সংকলকটি ভেরিয়েন্স চেকের ত্রুটিগুলির সাথে আপত্তি জানাবে

সেক্ষেত্রে আপনি অতিরিক্ত বৈশিষ্ট্যে সমস্ত ধরণের প্রয়োজনীয়তা সংগ্রহ করতে এবং এটির অন্যান্য বৈশিষ্ট্যগুলিকে প্যারাম্যাট্রাইজ করতে পারেন

//one trait to rule them all
trait OO[O <: OO[O]] { this : O =>
  type A <: AA[O]
  type B <: BB[O]
  type C <: CC[O]
}
trait AA[O <: OO[O]] { this : O#A =>
  type A = O#A
  type B = O#B
  type C = O#C
  def left(l:B):C
  def right(r:C):B = r.left(this)
  def join(l:B, r:C):A
  def double(l:B, r:C):A = this.join( l.join(r,this), r.join(this,l) )
}
trait BB[O <: OO[O]] { this : O#B =>
  type A = O#A
  type B = O#B
  type C = O#C
  def left(l:C):A
  def right(r:A):C = r.left(this)
  def join(l:C, r:A):B
  def double(l:C, r:A):B = this.join( l.join(r,this), r.join(this,l) )
}
trait CC[O <: OO[O]] { this : O#C =>
  type A = O#A
  type B = O#B
  type C = O#C
  def left(l:A):B
  def right(r:B):A = r.left(this)
  def join(l:A, r:B):C
  def double(l:A, r:B):C = this.join( l.join(r,this), r.join(this,l) )
}

এখন আমরা বর্ণিত প্যাটার্নের জন্য কংক্রিট উপস্থাপনা লিখতে পারি, বাম সংজ্ঞায়িত করতে পারি এবং সমস্ত ক্লাসে পদ্ধতিতে যোগদান করতে পারি এবং বিনামূল্যে ডান এবং ডাবল পেতে পারি

class ReprO extends OO[ReprO] {
  override type A = ReprA
  override type B = ReprB
  override type C = ReprC
}
case class ReprA(data : Int) extends AA[ReprO] {
  override def left(l:B):C = ReprC(data - l.data)
  override def join(l:B, r:C) = ReprA(l.data + r.data)
}
case class ReprB(data : Int) extends BB[ReprO] {
  override def left(l:C):A = ReprA(data - l.data)
  override def join(l:C, r:A):B = ReprB(l.data + r.data)
}
case class ReprC(data : Int) extends CC[ReprO] {
  override def left(l:A):B = ReprB(data - l.data)
  override def join(l:A, r:B):C = ReprC(l.data + r.data)
}

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

তারা একে অপরের সাথে সংযোগ দেয় এবং জটিল বিমূর্ততা তৈরির জন্য ব্যবহার করা যেতে পারে যা কেবল একটির সাথে প্রকাশ করা যায় না।


0

আমি মনে করি যে এখানে খুব বেশি পার্থক্য নেই। প্রকার বিমূর্ত সদস্যদের কেবল অস্তিত্বমূলক প্রকার হিসাবে দেখা যেতে পারে যা কিছু অন্যান্য কার্যকরী ভাষায় রেকর্ড টাইপের অনুরূপ।

উদাহরণস্বরূপ, আমাদের রয়েছে:

class ListT {
  type T
  ...
}

এবং

class List[T] {...}

তারপরে ListTঠিক একই রকম List[_]। প্রকারের সদস্যদের আত্মবিশ্বাস হ'ল আমরা সুস্পষ্ট কংক্রিটের ধরণ ছাড়াই ক্লাস ব্যবহার করতে পারি এবং অনেকগুলি ধরণের পরামিতি এড়াতে পারি।

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