চক্রীয় নির্ভরতা দিয়ে শুরু করা যাক।
trait A {
selfA: B =>
def fa: Int }
trait B {
selfB: A =>
def fb: String }
যাইহোক, এই সমাধানটির পরিমিতিটি যতটা প্রথম দেখা যায় তত বড় নয়, কারণ আপনি নিজের প্রকারের স্বরূপকে ওভাররাইড করতে পারেন:
trait A1 extends A {
selfA1: B =>
override def fb = "B's String" }
trait B1 extends B {
selfB1: A =>
override def fa = "A's String" }
val myObj = new A1 with B1
যদিও, আপনি যদি কোনও স্ব-ধরণের সদস্যকে ওভাররাইড করেন তবে আপনি মূল সদস্যের অ্যাক্সেস হারাবেন, যা উত্তরাধিকার ব্যবহার করে সুপারের মাধ্যমে অ্যাক্সেস করা যেতে পারে। সুতরাং উত্তরাধিকার ব্যবহারের মাধ্যমে যা অর্জন করা হয়েছে তা হ'ল:
trait AB {
def fa: String
def fb: String }
trait A1 extends AB
{ override def fa = "A's String" }
trait B1 extends AB
{ override def fb = "B's String" }
val myObj = new A1 with B1
এখন আমি কেকের প্যাটার্নের সমস্ত সূক্ষ্মতা বোঝার দাবি করতে পারি না, তবে এটি আমাকে আঘাত করেছে যে মডিউলারিটি প্রয়োগের মূল পদ্ধতিটি উত্তরাধিকার বা স্ব-ধরণের পরিবর্তে রচনার মাধ্যমে।
উত্তরাধিকার সংস্করণটি সংক্ষিপ্ত, তবে আমি স্ব-ধরণের চেয়ে উত্তরাধিকারকে পছন্দ করি তার প্রধান কারণ হ'ল স্ব-প্রকারের সাথে আরম্ভের ক্রমটি সঠিকভাবে অর্জন করা আমার কাছে আরও জটিল বলে মনে হয়। তবে স্ব-প্রকারের সাথে আপনি করতে পারেন এমন কিছু জিনিস রয়েছে যা আপনি উত্তরাধিকারের সাথে করতে পারেন না। স্ব-প্রকারের জন্য টাইপ ব্যবহার করা যায় যখন উত্তরাধিকারের মতো একটি বৈশিষ্ট্য বা শ্রেণি প্রয়োজন:
trait Outer
{ type T1 }
trait S1
{ selfS1: Outer#T1 => } //Not possible with inheritance.
আপনি এমনকি করতে পারেন:
trait TypeBuster
{ this: Int with String => }
যদিও আপনি এটি ইনস্ট্যান্ট করতে পারবেন না। আমি কোনও ধরণের থেকে উত্তরাধিকারী হতে না পারার কোনও নিখুঁত কারণ দেখতে পাচ্ছি না তবে আমি অবশ্যই মনে করি যে পাথ কনস্ট্রাক্টর ক্লাস এবং বৈশিষ্ট্যগুলি রয়েছে কারণ আমাদের ধরণের কনস্ট্রাক্টর বৈশিষ্ট্য / শ্রেণি রয়েছে। দুর্ভাগ্যক্রমে
trait InnerA extends Outer#Inner //Doesn't compile
আমাদের এটি আছে:
trait Outer
{ trait Inner }
trait OuterA extends Outer
{ trait InnerA extends Inner }
trait OuterB extends Outer
{ trait InnerB extends Inner }
trait OuterFinal extends OuterA with OuterB
{ val myV = new InnerA with InnerB }
অথবা এটা:
trait Outer
{ trait Inner }
trait InnerA
{this: Outer#Inner =>}
trait InnerB
{this: Outer#Inner =>}
trait OuterFinal extends Outer
{ val myVal = new InnerA with InnerB with Inner }
একটি বিষয় যা আরও সহানুভূত হওয়া উচিত তা হ'ল বৈশিষ্ট্যগুলি ক্লাসগুলি প্রসারিত করতে পারে। এটি নির্দেশ করার জন্য ডেভিড ম্যাকলভারকে ধন্যবাদ। এখানে আমার নিজস্ব কোডের একটি উদাহরণ রয়েছে:
class ScnBase extends Frame
abstract class ScnVista[GT <: GeomBase[_ <: TypesD]](geomRI: GT) extends ScnBase with DescripHolder[GT] )
{ val geomR = geomRI }
trait EditScn[GT <: GeomBase[_ <: ScenTypes]] extends ScnVista[GT]
trait ScnVistaCyl[GT <: GeomBase[_ <: ScenTypes]] extends ScnVista[GT]
ScnBase
সুইং ফ্রেম বর্গ থেকে উত্তরাধিকারসূত্রে প্রাপ্ত , তাই এটি স্ব-ধরণ হিসাবে ব্যবহৃত হতে পারে এবং তারপরে শেষে (তাত্ক্ষণিক সময়ে) মেশানো যায়। তবে, val geomR
উত্তরাধিকারসূত্রে বৈশিষ্ট্যের দ্বারা এটি ব্যবহার করার আগে এটি সূচনা করা দরকার। সুতরাং আমাদের পূর্বের সূচনা প্রয়োগের জন্য একটি শ্রেণি প্রয়োজন geomR
। ক্লাসটি ScnVista
একাধিক অরথোগোনাল বৈশিষ্ট্য থেকে উত্তরাধিকার সূত্রে প্রাপ্ত হতে পারে যা এগুলি থেকে উত্তরাধিকার সূত্রে প্রাপ্ত হতে পারে। একাধিক ধরণের পরামিতি (জেনেরিকস) ব্যবহার করে মড্যুলারটির বিকল্প রূপ উপলব্ধ করা হয়।