স্কেলা কেস শ্রেণীর উত্তরাধিকার


91

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

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

এখন অবধি আমি কেবলমাত্র একটি একক কেস ক্লাস ব্যবহার করেছি, একটি পতাকা সহ যা মডেলটির ধরণকে আলাদা করে এবং মডেলটির ধরণের উপর ভিত্তি করে পৃথক সমস্ত পদ্ধতি যদি একটি if দিয়ে শুরু হয়। এটি বিরক্তিকর এবং নিরাপদে বেশ টাইপ নয়।

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

কেস ক্লাস থেকে উত্তরাধিকার সূত্রে আমার কী কী সমস্যা এবং সমস্যাগুলি সম্পর্কে সচেতন হওয়া উচিত? আমার ক্ষেত্রে এটি করার অর্থ কি?


4
আপনি কি নন-কেস ক্লাস থেকে উত্তরাধিকারী হতে পারেন না, বা একটি সাধারণ বৈশিষ্ট্য প্রসারিত করতে পারেন?
এডুয়ার্ডো

আমি নিশ্চিত না. ক্ষেত্রগুলি পূর্বপুরুষের মধ্যে সংজ্ঞায়িত করা হয়। আমি সেই ক্ষেত্রগুলির উপর ভিত্তি করে অনুলিপি পদ্ধতি, সমতা এবং তাই পেতে চাই। যদি আমি পিতামাতাকে একটি বিমূর্ত শ্রেণি এবং শিশুদের কেস ক্লাস হিসাবে ঘোষণা করি তবে এটি কি পিতামাতার সংজ্ঞায়িত অ্যাকাউন্টগুলির পরামিতিগুলিতে নেবে?
Andrea

আমি মনে করি না, আপনাকে বিমূর্ত অভিভাবক (বা বৈশিষ্ট্য) এবং টার্গেট কেস ক্লাস উভয় ক্ষেত্রে প্রপস সংজ্ঞায়িত করতে হবে। শেষ পর্যন্ত, প্রচুর ও 'বয়লারপ্লেট, তবে কমপক্ষে নিরাপদ টাইপ করুন
ভ্যাচুওলিয়েস

উত্তর:


121

কোড ডুপ্লিকেশন ছাড়াই কেস শ্রেণির উত্তরাধিকার এড়ানোর আমার পছন্দের উপায়টি কিছুটা সুস্পষ্ট: একটি সাধারণ (বিমূর্ত) বেস শ্রেণি তৈরি করুন:

abstract class Person {
  def name: String
  def age: Int
  // address and other properties
  // methods (ideally only accessors since it is a case class)
}

case class Employer(val name: String, val age: Int, val taxno: Int)
    extends Person

case class Employee(val name: String, val age: Int, val salary: Int)
    extends Person


আপনি যদি আরও সূক্ষ্ম-দানা হতে চান, তবে বৈশিষ্ট্যগুলিকে পৃথক বৈশিষ্ট্যে ভাগ করুন:

trait Identifiable { def name: String }
trait Locatable { def address: String }
// trait Ages { def age: Int }

case class Employer(val name: String, val address: String, val taxno: Int)
    extends Identifiable
    with    Locatable

case class Employee(val name: String, val address: String, val salary: Int)
    extends Identifiable
    with    Locatable

84
আপনি যেখানে কথা বলছেন এটি "কোড নকল ছাড়াই" কোথায়? হ্যাঁ, একটি চুক্তি কেস ক্লাস এবং তার পিতামাতার (গুলি) এর মধ্যে সংজ্ঞায়িত করা হয়েছে তবে আপনি এখনও প্রপস এক্স 2 লিখছেন
ভ্যাচুওলিয়েস

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

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

4
@ ভার্চুয়ালিয়েস আমি সম্পূর্ণরূপে সম্মত হই যে খুব সহজেই যদি সম্পত্তির পুনরাবৃত্তি সহজ উপায়ে এড়ানো যায়। একটি সংকলক প্লাগইন অবশ্যই কৌশলটি করতে পারে, তবে আমি এটিকে সহজ উপায় বলব না।
মাল্টে শোওয়ারহফ

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

40

যেহেতু এটি অনেকের কাছে একটি আকর্ষণীয় বিষয়, তাই আমি এখানে কিছুটা আলোকপাত করি।

আপনি নিম্নলিখিত পদ্ধতির সাথে যেতে পারেন:

// You can mark it as 'sealed'. Explained later.
sealed trait Person {
  def name: String
}

case class Employee(
  override val name: String,
  salary: Int
) extends Person

case class Tourist(
  override val name: String,
  bored: Boolean
) extends Person

হ্যাঁ, আপনাকে ক্ষেত্রগুলি নকল করতে হবে। আপনি যদি তা না করেন তবে অন্যান্য সমস্যার মধ্যে সঠিক সমতা প্রয়োগ করা সহজ হবে না ।

তবে, আপনাকে পদ্ধতি / ফাংশনগুলি নকল করতে হবে না।

কয়েকটি সংখ্যার অনুলিপি যদি আপনার কাছে তাত্পর্যপূর্ণ হয় তবে নিয়মিত ক্লাস ব্যবহার করুন তবে মনে রাখবেন যে তারা এফপিতে ভাল ফিট করে না।

বিকল্পভাবে, আপনি উত্তরাধিকারের পরিবর্তে রচনা ব্যবহার করতে পারেন:

case class Employee(
  person: Person,
  salary: Int
)

// In code:
val employee = ...
println(employee.person.name)

রচনাটি একটি বৈধ এবং একটি দৃ strategy় কৌশল যা আপনার পাশাপাশি বিবেচনা করা উচিত।

এবং যদি আপনি অবাক হন যে সিল করা বৈশিষ্টগুলি কী বোঝায় - এটি এমন কিছু যা কেবল একই ফাইলটিতে বাড়ানো যায়। অর্থাৎ উপরের দুটি কেস ক্লাস একই ফাইলে থাকতে হবে। এটি সম্পূর্ণরূপে সংকলক পরীক্ষার জন্য অনুমতি দেয়:

val x = Employee(name = "Jack", salary = 50000)

x match {
  case Employee(name) => println(s"I'm $name!")
}

একটি ত্রুটি দেয়:

warning: match is not exhaustive!
missing combination            Tourist

যা সত্যই কার্যকর। এখন আপনি অন্য ধরণের Person(জনগণ) সাথে ডিল করতে ভুলবেন না । Optionস্কালার ক্লাসটি মূলত এটিই করে।

যদি এটি আপনার পক্ষে গুরুত্বপূর্ণ না হয়, তবে আপনি এটিকে সিলবিহীন তৈরি করতে পারেন এবং কেস ক্লাসগুলি তাদের নিজের ফাইলগুলিতে ফেলে দিতে পারেন। এবং সম্ভবত রচনা সঙ্গে যেতে।


4
আমি মনে করি যে def nameবৈশিষ্ট্যটি হওয়া দরকার val name। আমার সংকলকটি আমাকে প্রাক্তনটির সাথে অ্যাক্সেসযোগ্য কোড সতর্কতা দিচ্ছিল।
বার

13

কেস ক্লাসগুলি মান অবজেক্টগুলির জন্য উপযুক্ত, অর্থাত্ কোনও বস্তু যা কোনও বৈশিষ্ট্য পরিবর্তন করে না এবং সমতার সাথে তুলনা করা যায়।

কিন্তু উত্তরাধিকারের উপস্থিতিতে সমান প্রয়োগ করা বরং জটিল। দুটি শ্রেণি বিবেচনা করুন:

class Point(x : Int, y : Int)

এবং

class ColoredPoint( x : Int, y : Int, c : Color) extends Point

সুতরাং সংজ্ঞা অনুযায়ী রঙিন পয়েন্ট (1,4, লাল) পয়েন্টের সমান হওয়া উচিত (1,4) তারা সর্বোপরি একই পয়েন্ট। সুতরাং রঙিন পয়েন্ট (1,4, নীল) এছাড়াও পয়েন্ট (1,4) এর সমান হওয়া উচিত, তাই না? তবে অবশ্যই কালারপয়েন্ট (1,4, লাল) রঙিন পয়েন্ট (1,4, নীল) এর সমান হওয়া উচিত নয়, কারণ তাদের বিভিন্ন রঙ রয়েছে। আপনি সেখানে যান, সাম্যতার সম্পর্কের একটি প্রাথমিক সম্পত্তি ভাঙা হয়।

হালনাগাদ

অন্য উত্তরে বর্ণিত হিসাবে আপনি প্রচুর সমস্যা সমাধানের বৈশিষ্ট্যগুলি থেকে উত্তরাধিকার ব্যবহার করতে পারেন। এমনকি আরও নমনীয় বিকল্প হ'ল প্রায়শই টাইপ ক্লাস ব্যবহার করা। দেখুন কি Scala টাইপ শ্রেণীর জন্য কারা উপযোগী? বা http://www.youtube.com/watch?v=sVMES4RZF-8


আমি বুঝতে এবং এটি সঙ্গে একমত। সুতরাং, যখন আপনি কোনও অ্যাপ্লিকেশন রাখেন যা বলুন, নিয়োগকর্তা এবং কর্মচারীদের নিয়ে কাজ করবেন তখন আপনি কী পরামর্শ দিবেন। ধরুন যে তারা সমস্ত ক্ষেত্র (নাম, ঠিকানা এবং এই জাতীয়) ভাগ করে নিয়েছে, কিছু পদ্ধতির মধ্যে একমাত্র পার্থক্য - উদাহরণস্বরূপ, কেউ একটি সংজ্ঞা দিতে চাইতে পারে Employer.fire(e: Emplooyee)তবে অন্যভাবে নয় round আমি দুটি পৃথক শ্রেণি তৈরি করতে চাই, যেহেতু তারা প্রকৃতপক্ষে বিভিন্ন বস্তুর প্রতিনিধিত্ব করে তবে উত্থাপিত পুনরাবৃত্তিটিও আমি অপছন্দ করি।
Andrea

প্রশ্নের সাথে এখানে টাইপ ক্লাস পদ্ধতির উদাহরণ পেয়েছেন? অর্থাত্ কেস ক্লাস সম্পর্কিত
ভ্যুচুয়ালিজ

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

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

7

এই পরিস্থিতিতে আমি উত্তরাধিকার পরিবর্তে রচনা ব্যবহার করার ঝোঁক

sealed trait IVehicle // tagging trait

case class Vehicle(color: String) extends IVehicle

case class Car(vehicle: Vehicle, doors: Int) extends IVehicle

val vehicle: IVehicle = ...

vehicle match {
  case Car(Vehicle(color), doors) => println(s"$color car with $doors doors")
  case Vehicle(color) => println(s"$color vehicle")
}

অবশ্যই আপনি আরও পরিশীলিত হায়ারার্কি এবং ম্যাচগুলি ব্যবহার করতে পারেন তবে আশা করি এটি আপনাকে একটি ধারণা দেয়। কীটি ক্লাসগুলি সরবরাহ করে এমন নেস্টেড এক্সট্র্যাক্টরগুলির সুবিধা নেওয়া


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