স্ব-ধরণের এবং বৈশিষ্ট্যযুক্ত সাবক্লাসগুলির মধ্যে পার্থক্য কী?


387

বৈশিষ্ট্যের জন্য একটি স্ব-টাইপ A:

trait B
trait A { this: B => }

বলে যে " Aএকটি কংক্রিট শ্রেণিতে মিশ্রিত করা যাবে না যা প্রসারিতও হয় না B"

অন্যদিকে, নিম্নলিখিত:

trait B
trait A extends B

বলে যে "A যে কোনও (কংক্রিট বা বিমূর্ত) শ্রেণিতে মেশানো বিতেও মিশ্রিত হবে"

এই দুটি বিবৃতি একই জিনিস মানে না? স্ব-টাইপটি কেবল একটি সহজ সংকলন-সময় ত্রুটির সম্ভাবনা তৈরি করতে পরিবেশন করে।

আমি কী মিস করছি?


আমি এখানে স্ব-ধরণের এবং বৈশিষ্ট্যগুলিতে সাবক্লাসিংয়ের মধ্যে পার্থক্যের বিষয়ে আগ্রহী। আমি স্ব-প্রকারের কয়েকটি সাধারণ ব্যবহার জানি; সাবটাইপিংয়ের মাধ্যমে তারা আরও পরিষ্কারভাবে একইভাবে করা হবে না এর কারণ আমি খুঁজে পাচ্ছি না।
ডেভ

32
কেউ স্ব-প্রকারের মধ্যে টাইপ পরামিতি ব্যবহার করতে পারে: trait A[Self] {this: Self => }আইনী, trait A[Self] extends Selfএটি নয়।
ব্লেসরব্লেড

3
একটি স্ব ধরণের একটি শ্রেণিও হতে পারে, তবে একটি বৈশিষ্ট্য কোনও শ্রেণীর কাছ থেকে উত্তরাধিকারী হতে পারে না।
সিভোগ্ট

10
@ সিভিওগ্ট: একটি বৈশিষ্ট্য একটি শ্রেণীর (কমপক্ষে 2.10 হিসাবে) উত্তরাধিকারী হতে পারে: পেস্টবিন.
এরিক কাপলুন

1
@ ব্লায়সারব্লেড: এটি এমন কোনও কিছু নয় যা একটি ছোট ভাষার পুনরায় নকশা দ্বারা সমাধান করা যেতে পারে, তবে মৌলিক সীমাবদ্ধতা নয়? (কমপক্ষে প্রশ্নের দৃষ্টিকোণ থেকে)
এরিক কাপলুন

উত্তর:


273

এটি মূলত নির্ভরতা ইনজেকশন হিসাবে ব্যবহৃত হয় , যেমন কেক প্যাটার্নে। স্কালায় কেক প্যাটার্ন সহ অনেকগুলি নির্ভরশীলতা ইনজেকশনের বিভিন্ন রূপকে কভার করার একটি দুর্দান্ত নিবন্ধ রয়েছে । আপনি যদি গুগল "কেক প্যাটার্ন এবং স্কেলা", আপনি উপস্থাপনা এবং ভিডিও সহ অনেক লিঙ্ক পাবেন। আপাতত, এখানে আরও একটি প্রশ্নের লিঙ্ক দেওয়া হয়েছে

এখন, কোনও স্ব-ধরণের এবং একটি বৈশিষ্ট্য বাড়ানোর মধ্যে পার্থক্য কী তা সহজ। তুমি যদি বল B extends A, তারপর B হয় একটি A। আপনি যখন স্ব-প্রকার ব্যবহার করেন তখন একটি B প্রয়োজনA । দুটি নির্দিষ্ট প্রয়োজনীয়তা রয়েছে যা স্ব-প্রকারের সাথে তৈরি করা হয়:

  1. যদি Bপ্রসারিত হয়, তবে আপনাকে একটি মিক্স-ইন করতে হবেA
  2. যখন একটি কংক্রিট শ্রেণি অবশেষে এই বৈশিষ্ট্যগুলিকে প্রসারিত / মিশ্রিত করে, কিছু শ্রেণি / বৈশিষ্ট্য অবশ্যই প্রয়োগ করা উচিত A

নিম্নলিখিত উদাহরণগুলি বিবেচনা করুন:

scala> trait User { def name: String }
defined trait User

scala> trait Tweeter {
     |   user: User =>
     |   def tweet(msg: String) = println(s"$name: $msg")
     | }
defined trait Tweeter

scala> trait Wrong extends Tweeter {
     |   def noCanDo = name
     | }
<console>:9: error: illegal inheritance;
 self-type Wrong does not conform to Tweeter's selftype Tweeter with User
       trait Wrong extends Tweeter {
                           ^
<console>:10: error: not found: value name
         def noCanDo = name
                       ^

যদি Tweeterএকটি সাবক্লাস হয় User, ত্রুটি হবে না। উপরের কোডে, আমাদের যখনই ব্যবহৃত হবে এমন একটি প্রয়োজন ছিল , তবে এটি সরবরাহ করা হয়নি , সুতরাং আমরা একটি ত্রুটি পেয়েছি। এখন, উপরোক্ত কোডটি এখনও সুযোগের মধ্যে রয়েছে, বিবেচনা করুন:UserTweeterUserWrong

scala> trait DummyUser extends User {
     |   override def name: String = "foo"
     | }
defined trait DummyUser

scala> trait Right extends Tweeter with User {
     |   val canDo = name
     | }
defined trait Right 

scala> trait RightAgain extends Tweeter with DummyUser {
     |   val canDo = name
     | }
defined trait RightAgain

সাথে Right, মিক্স-ইন করার প্রয়োজনটি Userসন্তুষ্ট। যাইহোক, উপরে উল্লিখিত দ্বিতীয় প্রয়োজনীয়তা সন্তুষ্ট নয়: বাস্তবায়নের বোঝা Userএখনও শ্রেণি / বৈশিষ্ট্যগুলির মধ্যে রয়েছে যা প্রসারিত Right

সঙ্গে RightAgainউভয় প্রয়োজনীয়তা সন্তুষ্ট। এ Userএবং এর একটি বাস্তবায়নUser সরবরাহ করা হয়।

আরও ব্যবহারিক ব্যবহারের ক্ষেত্রে, দয়া করে এই উত্তরটির শুরুতে লিঙ্কগুলি দেখুন! তবে, আশা করি এখন আপনি এটি পেয়ে গেছেন।


3
ধন্যবাদ। আমি স্ব-প্রকারের চারপাশে হাইপ সম্পর্কে কেন কথা বলি তার মানে হ'ল 90% এর পিষ্টের প্যাটার্নটি ... আমি এখানে প্রথমে বিষয়টি দেখেছি। জোনাস বোনারের উদাহরণটি দুর্দান্ত কারণ এটি আমার প্রশ্নের মূল বিষয়টিকে আন্ডারস্কোর করে। আপনি যদি তার হিটার উদাহরণে স্ব-প্রকারগুলি সাবট্রাইটস হিসাবে পরিবর্তন করেন তবে তারতম্য কী হবে (আপনি যদি সঠিক উপাদানগুলিতে মেশেন না তবে কম্পোনেন্টরেজিস্ট্রি সংজ্ঞায়িত করার সময় আপনি যে ত্রুটিটি পেয়েছেন তা ছাড়া অন্য কি?
ডেভ

29
@ ডেভ: আপনার মত trait WarmerComponentImpl extends SensorDeviceComponent with OnOffDeviceComponent? এটি WarmerComponentImplসেই ইন্টারফেসগুলি হতে পারে । তারা প্রসারিত যে কোনও কিছুর জন্য উপলভ্য হবে WarmerComponentImplযা স্পষ্টতই ভুল, কারণ এটি কোনও নয়SensorDeviceComponent , একটিও নয় OnOffDeviceComponent। একটি স্ব ধরণের হিসাবে, এই নির্ভরতা একচেটিয়াভাবে উপলব্ধ WarmerComponentImpl। একটি Listএকটি হিসাবে ব্যবহার করা যেতে পারে Arrayতদ্বিপরীত, এবং। তবে তারা কেবল একই জিনিস নয়।
ড্যানিয়েল সি সোব্রাল

10
ধন্যবাদ ড্যানিয়েল এটি সম্ভবত আমি যে প্রধান পার্থক্যটি খুঁজছিলাম is ব্যবহারিক সমস্যাটি হ'ল সাবক্লাসিং ব্যবহার করা আপনার ইন্টারফেসের কার্যকারিতা ফাঁস করবে যা আপনি চান না। এটি বৈশিষ্ট্যের জন্য আরও তাত্ত্বিক "নিয়মের অংশ" এর লঙ্ঘনের ফলাফল। স্ব-প্রকার অংশগুলির মধ্যে "ব্যবহার-এ" সম্পর্ককে প্রকাশ করে।
ডেভ

11
@ রডনি না, এটি করা উচিত নয়। প্রকৃতপক্ষে, thisস্ব-ধরণের সাথে ব্যবহার করা এমন বিষয় যা আমি নীচের দিকে লক্ষ্য করি, কারণ এটি কোনও অকারণে আসল কারণ নয় this
ড্যানিয়েল সি সোব্রাল

9
@ ওপেনাস চেষ্টা করুন self: Dep1 with Dep2 =>
ড্যানিয়েল সি সোব্রাল

156

স্ব-ধরণের আপনাকে চক্রীয় নির্ভরতা নির্ধারণ করতে দেয়। উদাহরণস্বরূপ, আপনি এটি অর্জন করতে পারেন:

trait A { self: B => }
trait B { self: A => }

উত্তরাধিকার ব্যবহারের extendsঅনুমতি দেয় না। চেষ্টা করুন:

trait A extends B
trait B extends A
error:  illegal cyclic reference involving trait A

ওডারস্কি বইতে, 33.5 বিভাগটি দেখুন (স্প্রেডশিট ইউআই অধ্যায় তৈরি করা হচ্ছে) যেখানে এটি উল্লেখ করেছে:

স্প্রেডশিট উদাহরণে, ক্লাস মডেল মূল্যায়নকারীর কাছ থেকে উত্তরাধিকার সূত্রে প্রাপ্ত হয় এবং এইভাবে এর মূল্যায়ন পদ্ধতিতে অ্যাক্সেস অর্জন করে। অন্যভাবে যেতে, শ্রেণি মূল্যায়নকারী এর স্ব-প্রকারটিকে মডেল হিসাবে সংজ্ঞায়িত করে:

package org.stairwaybook.scells
trait Evaluator { this: Model => ...

আশাকরি এটা সাহায্য করবে.


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

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

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

@ ড্যানিয়েলসি.সোব্রাল আপনার মন্তব্যের জন্য ধন্যবাদ হতে পারে তবে এই মুহুর্তে এটি আপনার অ্যাঞ্জারের চেয়ে আরও বেশি উন্নতি করেছে। উভয়কেই উজ্জীবিত করে :)
rintcius

কেন শুধু একটি বৈশিষ্ট্য এবি তৈরি করবেন না? যেহেতু বৈশিষ্ট্য A এবং B সর্বদা কোনও চূড়ান্ত শ্রেণিতে একত্রিত হতে হবে, কেন এগুলি প্রথম স্থানে আলাদা করুন?
ধনী অলিভার

56

একটি অতিরিক্ত পার্থক্য হ'ল স্ব-প্রকারগুলি নন-শ্রেণির প্রকারগুলি নির্দিষ্ট করতে পারে। এই ক্ষেত্রে

trait Foo{
   this: { def close:Unit} => 
   ...
}

এখানে স্ব-টাইপ একটি কাঠামোগত প্রকার। প্রভাবটি বলতে গেলে ফু-তে যে কোনও কিছু মিশ্রিত হয় অবশ্যই একটি নো-আরগ "ক্লোজ" পদ্ধতি রিটার্নিং ইউনিট বাস্তবায়ন করতে হবে। এটি হাঁস-টাইপিংয়ের জন্য নিরাপদ মিক্সিনগুলির অনুমতি দেয়।


41
আসলে আপনি স্ট্রাকচারাল ধরণের সাথেও উত্তরাধিকার ব্যবহার করতে পারেন: বিমূর্ত ক্লাস এ প্রসারিত হয় {ডিফ বন্ধ: ইউনিট}
অ্যাড্রিয়ান

12
আমি মনে করি কাঠামোগত টাইপিং প্রতিবিম্ব ব্যবহার করছে, সুতরাং অন্য কোনও পছন্দ না থাকলে কেবল তখনই ব্যবহার করুন ...
ইরান মেডান

@ অ্যাড্রিয়ান, আমি বিশ্বাস করি আপনার মন্তব্যটি ভুল। st বিমূর্ত শ্রেণি A বর্ধিত {ডিফ বন্ধ: ইউনিট} just কেবলমাত্র বস্তু সুপারক্লাস সহ একটি বিমূর্ত শ্রেণি। এটি অযৌক্তিক অভিব্যক্তিগুলির জন্য কেবল একটি স্কালার অনুমতিমূলক বাক্য গঠন। আপনি দশম শ্রেণি প্রসারিত করতে পারেন {Def f = 1}; নতুন এক্স ()। f` উদাহরণস্বরূপ
অ্যালেক্সি

1
@ অ্যালেক্সি আমি দেখতে পাচ্ছি না কেন আপনার উদাহরণ (বা আমার) অযৌক্তিক।
অ্যাড্রিয়ান

1
@ অ্যাড্রিয়ান, abstract class A extends {def close:Unit}এর সমতুল্য abstract class A {def close:Unit}। সুতরাং এটি কাঠামোগত ধরনের জড়িত না।
আলেক্সি

13

মার্টিন ওডারস্কির আসল স্কালাল কাগজটির বিভাগ 2.3 "স্ব-ধরণের টিকা" স্কেলিয়েবল কম্পোনেন্ট অ্যাবস্ট্রাকশনগুলিরআসলে মিক্সিন সংমিশ্রণের বাইরে স্ব-টাইপের উদ্দেশ্যটি খুব ভালভাবে ব্যাখ্যা করে: একটি বিমূর্ত প্রকারের সাথে কোনও শ্রেণিকে যুক্ত করার বিকল্প উপায় সরবরাহ করে।

কাগজে প্রদত্ত উদাহরণটি নীচের মতো ছিল এবং এটিতে মার্জিত সাবক্লাস সংবাদদাতা বলে মনে হয় না:

abstract class Graph {
  type Node <: BaseNode;
  class BaseNode {
    self: Node =>
    def connectWith(n: Node): Edge =
      new Edge(self, n);
  }
  class Edge(from: Node, to: Node) {
    def source() = from;
    def target() = to;
  }
}

class LabeledGraph extends Graph {
  class Node(label: String) extends BaseNode {
    def getLabel: String = label;
    def self: Node = this;
  }
}

সাবক্লাসিং কেন এটি সমাধান করবে না তা ভাবতে তাদের জন্য, বিভাগ ২.৩ এও বলেছে: "সি_এন সহ মিক্সিন সংমিশ্রণ সিটি-এর প্রতিটি অপারেন্ড অবশ্যই একটি শ্রেণি পড়বে। মেশিন সংমিশ্রণ প্রক্রিয়াটি কোনও সি_আইকে কোনও বিমূর্ত প্রকারের উল্লেখ করতে দেয় না। এই বিধিনিষেধটি স্থিতিশীলভাবে অস্পষ্টতাগুলি পরীক্ষা করা এবং কোনও শ্রেণীর সমন্বয়ে গঠিত দ্বন্দ্বগুলিকে ওভাররাইড করা সম্ভব করে তোলে। "
লুক মোরার

12

অন্য একটি বিষয় যা উল্লেখ করা যায় নি: কারণ স্ব-প্রকারগুলি প্রয়োজনীয় শ্রেণীর শ্রেণিবিন্যাসের অংশ নয়, তারা প্যাটার্ন ম্যাচিং থেকে বাদ দেওয়া যেতে পারে, বিশেষত যখন আপনি সিল করে দেওয়া শ্রেণিবিন্যাসের সাথে পরিস্কারভাবে মেলে থাকেন। আপনি যখন অर्थোগোনাল আচরণগুলি যেমন মডেল করতে চান এটি সুবিধাজনক:

sealed trait Person
trait Student extends Person
trait Teacher extends Person
trait Adult { this : Person => } // orthogonal to its condition

val p : Person = new Student {}
p match {
  case s : Student => println("a student")
  case t : Teacher => println("a teacher")
} // that's it we're exhaustive

10

অন্যান্য উত্তরের টিআর; ডিআর সংক্ষিপ্তসার:

  • আপনার প্রসারিত প্রকারগুলি উত্তরাধিকার সূত্রে প্রাপ্ত ধরণের ক্ষেত্রে প্রকাশিত হয় তবে স্ব-প্রকারগুলি তা নয়

    উদাহরণস্বরূপ: class Cow { this: FourStomachs }আপনাকে কেবল rumeants এর জন্য উপলভ্য পদ্ধতিগুলি ব্যবহার করতে দেয়, যেমন digestGrass। গরু প্রসারিত বৈশিষ্ট্যগুলিতে এই জাতীয় সুবিধা নেই। অন্যদিকে, যে কাউকে class Cow extends FourStomachsপ্রকাশ digestGrassকরা হবে extends Cow

  • স্ব-প্রকারগুলি চক্রীয় নির্ভরতা দেয়, অন্য ধরণের প্রসারিত করে না


9

চক্রীয় নির্ভরতা দিয়ে শুরু করা যাক।

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একাধিক অরথোগোনাল বৈশিষ্ট্য থেকে উত্তরাধিকার সূত্রে প্রাপ্ত হতে পারে যা এগুলি থেকে উত্তরাধিকার সূত্রে প্রাপ্ত হতে পারে। একাধিক ধরণের পরামিতি (জেনেরিকস) ব্যবহার করে মড্যুলারটির বিকল্প রূপ উপলব্ধ করা হয়।


7
trait A { def x = 1 }
trait B extends A { override def x = super.x * 5 }
trait C1 extends B { override def x = 2 }
trait C2 extends A { this: B => override def x = 2}

// 1.
println((new C1 with B).x) // 2
println((new C2 with B).x) // 10

// 2.
trait X {
  type SomeA <: A
  trait Inner1 { this: SomeA => } // compiles ok
  trait Inner2 extends SomeA {} // doesn't compile
}

4

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


3
@ ব্লাইজারব্ল্যাড: আমি অবাক হই যে আপনার কিকিবোবোর উত্তর ভুল লেখা আছে কিনা - একটি বৈশিষ্ট্যের স্ব-স্বরূপ আপনাকে প্রকৃতপক্ষে যে ধরণের মিশ্রণ করতে পারে সেগুলি সীমাবদ্ধ রাখতে দেয় এবং এটি তার উপযোগিতার অংশ। উদাহরণস্বরূপ, আমরা যদি সংজ্ঞায়িত করি trait A { self:B => ... }তবে X with Aএক্স বি বি প্রসারিত হলে কেবলমাত্র একটি ঘোষণার বৈধতা আছে হ্যাঁ, আপনি বলতে পারেন X with A with Q, যেখানে প্রশ্ন বি বি প্রসারণ করে না, তবে আমি বিশ্বাস করি কিকিবোবোর বক্তব্যটি এক্স এতটাই বাধা ছিল। নাকি আমি কিছু মিস করেছি?
AmigoNico

1
ধন্যবাদ, আপনি ঠিক বলেছেন। আমার ভোটটি লক হয়ে গেছে তবে ভাগ্যক্রমে আমি উত্তরটি সম্পাদনা করতে এবং তারপরে আমার ভোট পরিবর্তন করতে পারলাম।
ব্লেসরব্লেড

1

আপডেট: একটি মূল পার্থক্য হ'ল স্ব-প্রকারগুলি একাধিক ক্লাসের উপর নির্ভর করতে পারে (আমি স্বীকার করি যে এটি কিছুটা কোণার ক্ষেত্রে)। উদাহরণস্বরূপ, আপনি থাকতে পারেন

class Person {
  //...
  def name: String = "...";
}

class Expense {
  def cost: Int = 123;
}

trait Employee {
  this: Person with Expense =>
  // ...

  def roomNo: Int;

  def officeLabel: String = name + "/" + roomNo;
}

এটি Employeeমিক্সিনকে কেবল যে কোনও কিছুর সাথে যুক্ত করতে দেয় যা একটি Personএবং একটি সাবক্লাস Expense। অবশ্যই, এটি কেবল তখনই অর্থবহ হয় যদি Expenseপ্রসারিত হয় Personবা বিপরীত হয়। মুল বক্তব্যটি হ'ল স্ব-প্রকারগুলি ব্যবহার করা Employeeক্লাসগুলির শ্রেণিবিন্যাসের থেকে পৃথক হতে পারে depends এটা কি কি প্রসারিত পরোয়া করে না - আপনি অনুক্রমের সুইচ যদি Expenseবনাম Person, আপনি পরিবর্তন করতে হবে না Employee


ব্যক্তির কাছ থেকে অবতরণ করার জন্য কর্মচারীর কোনও শ্রেণি হওয়ার দরকার নেই। বৈশিষ্ট্য ক্লাস প্রসারিত করতে পারে। যদি কর্মচারীর বৈশিষ্ট্য স্ব-প্রকারের পরিবর্তে ব্যক্তিকে প্রসারিত করে তবে উদাহরণটি এখনও কাজ করবে। আমি আপনার উদাহরণ আকর্ষণীয় মনে করি, তবে এটি স্ব-প্রকারের জন্য কোনও ব্যবহারের ক্ষেত্রে চিত্রিত বলে মনে হয় না।
মরগান ক্রেইটন

@ মরগানক্রাইটন ফেয়ার পর্যাপ্ত, আমি জানতাম না যে বৈশিষ্ট্যগুলি শ্রেণিবদ্ধ করতে পারে। আমি আরও ভাল উদাহরণ খুঁজে পেতে পারেন যদি আমি এটি সম্পর্কে চিন্তা করব।
পেটর পুদলক

হ্যাঁ, এটি একটি আশ্চর্যজনক ভাষা বৈশিষ্ট্য। যদি বৈশিষ্ট্যযুক্ত কর্মচারী বর্ধমান শ্রেণীর ব্যক্তি হন, তবে কর্মচারী যে কোনও শ্রেণিই শেষ পর্যন্ত "বুদ্ধিমান" হয়ে থাকে তাকেও ব্যক্তিকে প্রসারিত করতে হবে। কিন্তু সেই সীমাবদ্ধতা এখনও উপস্থিত রয়েছে যদি কর্মচারী ব্যক্তিকে বাড়ানোর পরিবর্তে কোনও স্ব-ধরণ ব্যবহার করে। চিয়ার্স, পেট্র!
মরগান ক্রেইটন

1
আমি কেন দেখছি না "ব্যয় ব্যক্তির বিপরীতে বা তার বিপরীতে প্রসারিত হলে এটি কেবল অর্থবহ"।
রবিন গ্রিন

0

প্রথম ক্ষেত্রে, বি এর একটি উপ-বৈশিষ্ট্য বা উপ-শ্রেণীর যেকোন ব্যবহারের সাথে মিশ্রিত করা যেতে পারে এ। বি বিমূর্ত বৈশিষ্ট্য হতে পারে।


না, বি উভয় ক্ষেত্রেই (এবং প্রকৃতপক্ষে) একটি "বিমূর্ত বৈশিষ্ট্য" হতে পারে। সুতরাং সেই দৃষ্টিকোণ থেকে কোনও পার্থক্য নেই।
রবিন গ্রিন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.