কেস অবজেক্টস স্ক্যামে বনাম গণনাগুলি


231

স্কালায় গণনা বৃদ্ধি বা বনাম কেস ক্লাস (বা কেস অবজেক্টস) কখন ব্যবহার করবেন সে সম্পর্কে কোনও সেরা-অনুশীলনের গাইডলাইন রয়েছে ?

তারা একই সুবিধা বঞ্চিত বলে মনে হচ্ছে।


2
আমি স্কেল অঙ্ক এবং বিকল্পগুলি সম্পর্কে একটি ছোট ওভারভিউ লিখেছি, আপনি এটি দরকারী খুঁজে পেতে পারেন: pedrorijo.com/blog/scala-enums/
pedrorijo91

1
আরও দেখুন ছিটগ্রস্ত ভিত্তিক Scala 3enum (মধ্য 2020 জন্য)।
ভোনসি

উত্তর:


223

একটি বড় পার্থক্য হ'ল Enumerationকিছু nameস্ট্রিং থেকে তাদের ইনস্ট্যান্ট করার জন্য সমর্থন নিয়ে আসা । উদাহরণ স্বরূপ:

object Currency extends Enumeration {
   val GBP = Value("GBP")
   val EUR = Value("EUR") //etc.
} 

তারপরে আপনি এটি করতে পারেন:

val ccy = Currency.withName("EUR")

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

sealed trait Currency { def name: String }
case object EUR extends Currency { val name = "EUR" } //etc.

case class UnknownCurrency(name: String) extends Currency

সুতরাং এখন আমার সুবিধা আছে ...

trade.ccy match {
  case EUR                   =>
  case UnknownCurrency(code) =>
}

যেমন @ বিশৃঙ্খল 3 কিলিব্রিয়াম উল্লেখ করা হয়েছে (পড়া সহজ করার জন্য কিছু সংশোধন সহ):

"অজানা কারকেন্সি (কোড)" প্যাটার্ন সম্পর্কিত, মুদ্রা কোড স্ট্রিং না পাওয়াটিকে পরিচালনা করার অন্যান্য উপায় রয়েছে যা বন্ধ করে দেওয়া প্রকৃতির "ভঙ্গ" করার চেয়ে Currency ধরণের । UnknownCurrencyধরণের হচ্ছেCurrency এখন একটি এপিআই এর অন্যান্য অংশে ছিঁচকে দেখতে পারে।

এই কেসটিকে বাইরে ঠেলে দেওয়া ভাল Enumeration এবং ক্লায়েন্টকে এমন Option[Currency]ধরণের সাথে চুক্তি যা স্পষ্টভাবে ইঙ্গিত দেয় যে সত্যিই কোনও মিলের সমস্যা রয়েছে এবং এটিআইপি-র ব্যবহারকারীকে "নিজেকে উত্সাহিত করা" এটিকে তার নিজের থেকে বাছাই করতে।

অন্যান্য উত্তরগুলি এখানে অনুসরণ করতে, প্রধান সমস্যার মধ্যে case objectরয়েছেEnumeration এর :

  1. "গণনা" এর সমস্ত দৃষ্টান্তে পুনরাবৃত্তি করতে পারে না । এটি অবশ্যই কেস, তবে আমি অনুশীলনে এটি অত্যন্ত বিরল বলে মনে করেছি যে এটি প্রয়োজনীয়।

  2. স্থির মান থেকে সহজেই ইনস্ট্যান্ট করতে পারে না । এটিও সত্য তবে বিশাল অঙ্কের ক্ষেত্রে (উদাহরণস্বরূপ, সমস্ত মুদ্রা) বাদে এটি একটি বিশাল ওভারহেড উপস্থাপন করে না।


10
অন্য পার্থক্যটি হ'ল এনুমুরেশন এনুমকে বাক্সের বাইরে অর্ডার দেওয়া হয়েছে, তবে কেস অবজেক্ট বেইজড এনাম অবিস্মরণীয়ভাবে নয়
সর্বনাম-নাম-

1
কেস অবজেক্টগুলির জন্য আরেকটি বিষয় হ'ল আপনি যদি জাভা আন্তঃব্যবহারের বিষয়ে যত্নশীল হন। অঙ্কটি মূল্যায়ন হিসাবে মূল্যগুলি ফিরিয়ে দেবে V মূল্য, সুতরাং 1) স্কালার লাইব্রেরি প্রয়োজন, 2) প্রকৃত ধরণের তথ্য হারাতে।
জুয়ানমার্কস

7
@ অক্সবো_লাক্স পয়েন্ট ১ সম্পর্কিত, বিশেষত এই অংশটি "... আমি অনুশীলনে এটি অত্যন্ত বিরল বলে মনে করেছি যে এটি প্রয়োজন": সম্ভবত আপনি খুব কমই ইউআই কাজ করেন। এটি একটি অত্যন্ত সাধারণ ব্যবহারের কেস; বৈধ গণনা সদস্যদের একটি (ড্রপ-ডাউন) তালিকা প্রদর্শন করা হচ্ছে যা থেকে নেওয়া হবে।
বিশৃঙ্খলা

trade.ccyসিল করা বৈশিষ্ট উদাহরণে আইটেমটির ধরণটি কীভাবে মিলছে তা আমি বুঝতে পারি না ।
rloth

এবং case objectএর চেয়ে বড় (x 4x) কোডের পদাঙ্কগুলি জেনারেট করে না Enumeration? বিশেষত scala.jsছোট পদক্ষেপের প্রয়োজন এমন প্রকল্পগুলির জন্য দরকারী পার্থক্য ।
ইকো

69

আপডেট: একটি নতুন ম্যাক্রো ভিত্তিক সমাধান তৈরি করা হয়েছে যা নীচের রূপরেখার সমাধানের তুলনায় অনেক বেশি উন্নত। আমি দৃ new ়ভাবে এই নতুন ম্যাক্রো ভিত্তিক সমাধান ব্যবহার করার পরামর্শ দিচ্ছি । এবং মনে হয় ডটিটির পরিকল্পনাগুলি এই শৈলীর এনাম সলিউশনটিকে ভাষার অংশ হিসাবে তৈরি করবে। Whoohoo!

সংক্ষিপ্তসার: স্কালার একটি প্রকল্পের মধ্যে
জাভা পুনরুত্পাদন করার চেষ্টা করার জন্য তিনটি প্রাথমিক নিদর্শন রয়েছে Enum। তিনটি নিদর্শনগুলির মধ্যে দুটি; সরাসরি জাভা ব্যবহার করে Enumএবং scala.Enumeration, স্কালার বিস্তৃত প্যাটার্ন মেলানো সক্ষম করতে সক্ষম নয়। এবং তৃতীয়টি; "সিলড বৈশিষ্ট্য + কেস অবজেক্ট", করে ... তবে জেভিএম শ্রেণি / অবজেক্টের সূচনা জটিলতা রয়েছে যার ফলে বেমানান অর্ডিনাল সূচক তৈরি হয়।

আমি দুটি ক্লাস নিয়ে একটি সমাধান তৈরি করেছি; গণনা এবং গণনা ডেকোর্টেড , এই গিস্টে অবস্থিত । আমি এই থ্রেডে কোডটি পোস্ট করিনি কারণ গণনার জন্য ফাইলটি বেশ বড় (+400 লাইন - বাস্তবায়নের প্রসঙ্গে ব্যাখ্যা করার জন্য প্রচুর মন্তব্য রয়েছে)।

বিশদ:
আপনি যে প্রশ্নটি জিজ্ঞাসা করছেন তা বেশ সাধারণ; "... বর্ধিত caseক্লাস কখন ব্যবহার করবেনobjects[scala.]Enumeration "। এবং এটিতে দেখা যাচ্ছে যে অনেকগুলি সম্ভাব্য উত্তর রয়েছে, প্রতিটি উত্তর আপনার নির্দিষ্ট প্রকল্পের প্রয়োজনীয়তার সূক্ষ্মতার উপর নির্ভর করে। উত্তরটি তিনটি বেসিক নিদর্শনকে কমিয়ে আনা যায়।

শুরু করার জন্য, আসুন নিশ্চিত করা যাক আমরা একটি গণনা কী তা একই বুনিয়াদি ধারণা থেকে কাজ করছি। আসুন Enumজাভা 5 (1.5) হিসাবে প্রদত্ত শর্তাবলী মূলত একটি গণনা সংজ্ঞায়িত করা যাক :

  1. এটিতে নামযুক্ত সদস্যদের একটি প্রাকৃতিক অর্ডার দেওয়া বদ্ধ সেট রয়েছে
    1. সদস্যদের একটি নির্দিষ্ট সংখ্যা আছে
    2. সদস্যদের স্বাভাবিকভাবে আদেশ করা হয় এবং সুস্পষ্টভাবে সূচকযুক্ত হয়
      • কিছু inate সদস্য জিজ্ঞাস্য মানদণ্ডের ভিত্তিতে বাছাই করা বিরোধী হিসাবে
    3. সমস্ত সদস্যের মোট সেটের মধ্যে প্রতিটি সদস্যের একটি অনন্য নাম রয়েছে
  2. সমস্ত সদস্যকে সহজেই তাদের সূচকগুলির উপর নির্ভর করে পুনরাবৃত্তি করা যেতে পারে
  3. কোনও সদস্যকে তার (কেস সেনসিটিভ) নাম দিয়ে পুনরুদ্ধার করা যায়
    1. এটি বেশ সুন্দর হবে যদি কোনও সদস্যকে তার ক্ষেত্রে সংবেদনশীল নামও পাওয়া যায়
  4. কোনও সদস্যকে এর সূচক দিয়ে পুনরুদ্ধার করা যায়
  5. সদস্যগণ সহজেই, স্বচ্ছ এবং দক্ষতার সাথে সিরিয়ালাইজেশন ব্যবহার করতে পারেন
  6. অতিরিক্ত সংযুক্ত সিঙ্গলটন-নেস ডেটা রাখতে সদস্যদের সহজেই বাড়ানো যেতে পারে
  7. জাভা এর বাইরে চিন্তাভাবনা করে Enum, স্কালার প্যাটার্নের সাথে পরিমাপের পরিসংখ্যানের সাথে পরিসংখ্যান পরীক্ষা করার জন্য স্পষ্টভাবে লাভ করতে সক্ষম হবেন

এর পরে, পোস্ট হওয়া তিনটি সাধারণ সমাধান নিদর্শনগুলির সিদ্ধ সংস্করণগুলি দেখুন:

ক) আসলে সরাসরি জাভাEnum প্যাটার্ন ব্যবহার করে (একটি মিশ্র স্কেলা / জাভা প্রকল্পে):

public enum ChessPiece {
    KING('K', 0)
  , QUEEN('Q', 9)
  , BISHOP('B', 3)
  , KNIGHT('N', 3)
  , ROOK('R', 5)
  , PAWN('P', 1)
  ;

  private char character;
  private int pointValue;

  private ChessPiece(char character, int pointValue) {
    this.character = character; 
    this.pointValue = pointValue;   
  }

  public int getCharacter() {
    return character;
  }

  public int getPointValue() {
    return pointValue;
  }
}

গণনা সংজ্ঞা থেকে নিম্নলিখিত আইটেমগুলি উপলভ্য নয়:

  1. ৩.১ - এটির পক্ষে যদি খুব ভাল লাগবে যে কোনও সদস্যকে তার ক্ষেত্রে সংবেদনশীল নামও পাওয়া যায়
  2. 7 - জাভার এনামের বাইরে চিন্তাভাবনা করা, স্কালার প্যাটার্নের সাথে পরিমাপের পরিমাপের সাথে পরিসংখ্যানের পরীক্ষার সুস্পষ্টভাবে উপকার করতে সক্ষম হবেন

আমার বর্তমান প্রকল্পগুলির জন্য, স্কালা / জাভা মিশ্র প্রকল্পের পথের আশেপাশে ঝুঁকি নেওয়ার সুবিধা আমার নেই। এমনকি আমি যদি একটি মিশ্র প্রকল্পটি বেছে নিতে পারি, আইটেম আমাকে / যখন আমি হয় গণনা সদস্যদের যুক্ত / সরিয়ে ফেলা, বা বিদ্যমান গণনা সদস্যদের সাথে ডিল করার জন্য কিছু নতুন কোড লিখছি তখন আমাকে সংকলনের সময় সমস্যাগুলি ধরার অনুমতি দেওয়ার জন্য গুরুত্বপূর্ণ।


খ) " sealed trait+case objects " প্যাটার্ন ব্যবহার করে :

sealed trait ChessPiece {def character: Char; def pointValue: Int}
object ChessPiece {
  case object KING extends ChessPiece {val character = 'K'; val pointValue = 0}
  case object QUEEN extends ChessPiece {val character = 'Q'; val pointValue = 9}
  case object BISHOP extends ChessPiece {val character = 'B'; val pointValue = 3}
  case object KNIGHT extends ChessPiece {val character = 'N'; val pointValue = 3}
  case object ROOK extends ChessPiece {val character = 'R'; val pointValue = 5}
  case object PAWN extends ChessPiece {val character = 'P'; val pointValue = 1}
}

গণনা সংজ্ঞা থেকে নিম্নলিখিত আইটেমগুলি উপলভ্য নয়:

  1. 1.2 - সদস্যদের স্বাভাবিকভাবে আদেশ করা হয় এবং সুস্পষ্টভাবে সূচকযুক্ত হয়
  2. 2 - সমস্ত সদস্যকে সহজেই তাদের সূচকগুলির উপর নির্ভর করে পুনরাবৃত্তি করা যায়
  3. 3 - কোনও সদস্যকে তার (কেস সেনসিটিভ) নাম দিয়ে পুনরুদ্ধার করা যায়
  4. ৩.১ - এটির পক্ষে যদি খুব ভাল লাগবে যে কোনও সদস্যকে তার ক্ষেত্রে সংবেদনশীল নামও পাওয়া যায়
  5. 4 - কোনও সদস্যকে এর সূচক দিয়ে পুনরুদ্ধার করা যায়

এটি বিতর্কযুক্ত এটি সত্যই গণনা সংজ্ঞা আইটেম 5 এবং 6 পূরণ করে 5 জন্য, এটি দক্ষ বলে দাবি করা একটি প্রসারিত। 6 এর জন্য, অতিরিক্ত যুক্ত একক-নেস ডেটা ধরে রাখা প্রসারিত করা সত্যিই সহজ নয়।


গ)scala.Enumeration প্যাটার্নটি ব্যবহার করুন ( এই স্ট্যাকওভারফ্লো উত্তরটি দ্বারা অনুপ্রাণিত ):

object ChessPiece extends Enumeration {
  val KING = ChessPieceVal('K', 0)
  val QUEEN = ChessPieceVal('Q', 9)
  val BISHOP = ChessPieceVal('B', 3)
  val KNIGHT = ChessPieceVal('N', 3)
  val ROOK = ChessPieceVal('R', 5)
  val PAWN = ChessPieceVal('P', 1)
  protected case class ChessPieceVal(character: Char, pointValue: Int) extends super.Val()
  implicit def convert(value: Value) = value.asInstanceOf[ChessPieceVal]
}

গণনা সংজ্ঞা থেকে নিম্নলিখিত আইটেমগুলি উপলভ্য নয় (সরাসরি জাভা এনাম ব্যবহারের জন্য তালিকার সাথে অভিন্ন বলে মনে হচ্ছে):

  1. ৩.১ - এটির পক্ষে যদি খুব ভাল লাগবে যে কোনও সদস্যকে তার ক্ষেত্রে সংবেদনশীল নামও পাওয়া যায়
  2. 7 - জাভার এনামের বাইরে চিন্তাভাবনা করা, স্কালার প্যাটার্নের সাথে পরিমাপের পরিমাপের সাথে পরিসংখ্যানের পরীক্ষার সুস্পষ্টভাবে উপকার করতে সক্ষম হবেন

আবার আমার বর্তমান প্রকল্পগুলির জন্য, আইটেম 7 আমাকে সংকলনের সদস্যদের যুক্ত / সরিয়ে ফেলা বা বিদ্যমান গণনা সদস্যদের সাথে ডিল করার জন্য কিছু নতুন কোড লিখতে থাকলে / আমাকে সংকলিত সময়ের সমস্যাগুলি ধরার অনুমতি দেওয়ার জন্য গুরুত্বপূর্ণ।


সুতরাং, একটি গণনার উপরোক্ত সংজ্ঞা দেওয়া, উপরের তিনটি সমাধানের মধ্যে কোনওটিই কাজ করে না কারণ তারা উপরের গণনার সংজ্ঞায় বর্ণিত সমস্ত কিছুই সরবরাহ করে না:

  1. জাভা এনাম সরাসরি একটি মিশ্র স্কেলা / জাভা প্রকল্পে
  2. "সিলড বৈশিষ্ট্য + কেস অবজেক্টস"
  3. scala.Enumeration

এর প্রতিটি সমাধানের অবশেষে প্রত্যেকে নিখোঁজ হওয়া প্রয়োজনীয়তার কিছু আবরণ করার চেষ্টা করার জন্য পুনর্নির্মাণ / প্রসারিত / রিফ্যাক্টর করা যেতে পারে। যাইহোক, জাভা Enumবা scala.Enumerationসমাধানগুলি উভয়ই আইটেম 7 সরবরাহের জন্য পর্যাপ্ত পরিমাণে প্রসারিত হতে পারে না And এবং আমার নিজের প্রকল্পগুলির জন্য, এটি স্কালার মধ্যে একটি বদ্ধ প্রকারের ব্যবহারের আরও বাধ্যযোগ্য মান। আমি প্রোডাক্ট রানটাইম ব্যতিক্রম / ব্যর্থতা থেকে বেরিয়ে যাওয়ার বিপরীতে আমার কোডে ফাঁক / ইস্যু রয়েছে তা নির্দেশ করতে আমি দৃ strongly়ভাবে সংকলন সময়ের সতর্কতা / ত্রুটি পছন্দ করি।


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

আমার সমাধান দুটি বৈশিষ্ট্য হিসাবে; গণনা এবং গণনাEnumeration ডেকোর্টেড , এবং যেহেতু বৈশিষ্ট্যটি +400 লাইন দীর্ঘ (প্রসঙ্গটি ব্যাখ্যা করার জন্য প্রচুর মন্তব্য) বেশি, তাই আমি এটি এই থ্রেডে আটকানোর জন্য যাচ্ছি (যা এটি পৃষ্ঠা বিবেচনা করে বিবেচনা করে প্রসারিত করবে)। বিশদ জন্য, সরাসরি টুকরো টুকরো লাফাতে ।

উপরের মত একই ডেটা আইডিয়াটি ব্যবহার করার মতো সমাধানটি কী শেষ হবে তা এখানে দেওয়া হয়েছে ( এখানে সম্পূর্ণরূপে মন্তব্য করা সংস্করণ উপলব্ধ রয়েছে ) এবং এতে প্রয়োগ করা হয়েছে EnumerationDecorated

import scala.reflect.runtime.universe.{TypeTag,typeTag}
import org.public_domain.scala.utils.EnumerationDecorated

object ChessPiecesEnhancedDecorated extends EnumerationDecorated {
  case object KING extends Member
  case object QUEEN extends Member
  case object BISHOP extends Member
  case object KNIGHT extends Member
  case object ROOK extends Member
  case object PAWN extends Member

  val decorationOrderedSet: List[Decoration] =
    List(
        Decoration(KING,   'K', 0)
      , Decoration(QUEEN,  'Q', 9)
      , Decoration(BISHOP, 'B', 3)
      , Decoration(KNIGHT, 'N', 3)
      , Decoration(ROOK,   'R', 5)
      , Decoration(PAWN,   'P', 1)
    )

  final case class Decoration private[ChessPiecesEnhancedDecorated] (member: Member, char: Char, pointValue: Int) extends DecorationBase {
    val description: String = member.name.toLowerCase.capitalize
  }
  override def typeTagMember: TypeTag[_] = typeTag[Member]
  sealed trait Member extends MemberDecorated
}

এটি গণনার সংজ্ঞায় কাঙ্ক্ষিত ও বর্ণিত সমস্ত ক্ষমতা বাস্তবায়নের জন্য আমি তৈরি করা একটি নতুন জোড়ের গুণমানের বৈশিষ্ট্য ( এই গিস্টে অবস্থিত ) এর একটি উদাহরণ ।

উদ্বেগ প্রকাশ করা একটি উদ্বেগ হ'ল গণনা সদস্যের নামগুলি অবশ্যই পুনরাবৃত্তি করতে হবে ( decorationOrderedSetউপরের উদাহরণে)। আমি যখন এটি একক পুনরাবৃত্তিতে হ্রাস করেছি, তখনও দুটি সমস্যার কারণে কীভাবে এটি আরও কম করা যায় তা আমি দেখতে পেলাম না:

  1. এই নির্দিষ্ট অবজেক্ট / কেস অবজেক্ট মডেলটির জন্য জেভিএম অবজেক্ট / ক্লাস ইনিশিয়ালাইজেশন পূর্বনির্ধারিত ( এই স্ট্যাকওভারফ্লো থ্রেডটি দেখুন )
  2. পদ্ধতিটি থেকে ফিরে আসা সামগ্রীর getClass.getDeclaredClassesএকটি অপরিজ্ঞাত অর্ডার রয়েছে (এবং case objectউত্স কোডে ঘোষণাপত্রের মতো একই ক্রমে হওয়ার সম্ভাবনা খুব কম )

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

এবং নকশার জন্য এই দ্বিতীয় তালিকা / সেট ক্রমটি প্রয়োজনীয় প্রয়োজন val, ChessPiecesEnhancedDecoratedউপরের উদাহরণটি দেওয়া হয়েছে , এটি যুক্ত করা সম্ভব হয়েছিল case object PAWN2 extends Memberএবং তারপরে যুক্ত Decoration(PAWN2,'P2', 2)করতে ভুলে গিয়েছিল decorationOrderedSet। সুতরাং, তালিকাটি কেবলমাত্র একটি সেট নয় তা যাচাই করার জন্য একটি রানটাইম চেক আছে, তবে এতে কেস অবজেক্টের সমস্ত রয়েছে যা প্রসারিত করে sealed trait Member। এটি কাজ করার জন্য প্রতিবিম্ব / ম্যাক্রো হেলকের একটি বিশেষ রূপ ছিল।


মন্তব্য এবং / অথবা গিস্ট উপর প্রতিক্রিয়া দয়া করে ।


আমি এখন স্কেলাওলিও লাইব্রেরির প্রথম সংস্করণ প্রকাশ করেছি (জিপিএলভি 3) যা উভয়টির আরও আধুনিক সংস্করণ org.scalaolio.util.Enumerationএবং org.scalaolio.util.EnumerationDecorated: scalaolio.org
বিশৃঙ্খল

এবং গিথুব-এ সরাসরি স্ক্যালালিয়ালিও সংগ্রহস্থলটিতে প্রত্যাশার জন্য: github.com/chaotic3quilibrium/scala-olio
বিশৃঙ্খলা

5
এটি একটি মানের উত্তর এবং এর থেকে নেওয়া অনেক কিছুই। আপনাকে ধন্যবাদ
অ্যাঙ্গাব্রিয়েল

1
দেখে মনে হচ্ছে ওডারস্কি একটি নেটিভ এনামের সাথে ডটি (ভবিষ্যতের স্কালা 3.0) আপগ্রেড করতে চাইছে। Whoohoo! github.com/lampepfl/dotty/issues/1970
বিশৃঙ্খল

62

কেস অবজেক্টগুলি তাদের স্ট্রিং পদ্ধতির জন্য ইতিমধ্যে তাদের নামটি ফিরিয়ে দেয়, তাই এটি আলাদাভাবে পাস করা অপ্রয়োজনীয়। এখানে ঝো'র অনুরূপ একটি সংস্করণ রয়েছে (ব্রেভিটির জন্য সুবিধাগুলি বাদ দেওয়া):

trait Enum[A] {
  trait Value { self: A => }
  val values: List[A]
}

sealed trait Currency extends Currency.Value
object Currency extends Enum[Currency] {
  case object EUR extends Currency
  case object GBP extends Currency
  val values = List(EUR, GBP)
}

বস্তুগুলি অলস; পরিবর্তে ভাল ব্যবহার করে আমরা তালিকাটি বাদ দিতে পারি তবে নামটি পুনরাবৃত্তি করতে হবে:

trait Enum[A <: {def name: String}] {
  trait Value { self: A =>
    _values :+= this
  }
  private var _values = List.empty[A]
  def values = _values
}

sealed abstract class Currency(val name: String) extends Currency.Value
object Currency extends Enum[Currency] {
  val EUR = new Currency("EUR") {}
  val GBP = new Currency("GBP") {}
}

আপনি যদি কিছু প্রতারণার বিষয়ে আপত্তি না দেখায় তবে আপনি প্রতিবিম্ব এপিআই বা গুগল প্রতিবিম্বের মতো কিছু ব্যবহার করে আপনার গণনা মানগুলি পূর্ব-লোড করতে পারেন। অ-অলস কেস অবজেক্টগুলি আপনাকে সবচেয়ে পরিষ্কার বাক্য গঠন দেয়:

trait Enum[A] {
  trait Value { self: A =>
    _values :+= this
  }
  private var _values = List.empty[A]
  def values = _values
}

sealed trait Currency extends Currency.Value
object Currency extends Enum[Currency] {
  case object EUR extends Currency
  case object GBP extends Currency
}

কেস ক্লাস এবং জাভা গণনার সমস্ত সুবিধা সহ সুন্দর এবং পরিষ্কার। ব্যক্তিগতভাবে, আমি আইডেম্যাটিক স্কাল কোডটির সাথে আরও ভাল মেলে বস্তুর বাইরে অঙ্কের মানগুলি সংজ্ঞায়িত করি:

object Currency extends Enum[Currency]
sealed trait Currency extends Currency.Value
case object EUR extends Currency
case object GBP extends Currency

3
একটি প্রশ্ন: শেষ সমাধানটিকে "নন অলস কেস অবজেক্টস" বলা হয় তবে এই ক্ষেত্রে অবজেক্টগুলি ব্যবহার না করা পর্যন্ত লোড করা হয় না: আপনি কেন এই সমাধানটিকে অলস বলছেন?
Seb Cesbron

2
@ নোয়েল, আপনাকে ব্যবহার করতে হবে: পুরো সিল করা শ্রেণিবিন্যাসকে আরপিএলে আটকানোর জন্য পেস্ট করুন। যদি আপনি এটি না করেন তবে সিল করা বেস ক্লাস / বৈশিষ্ট্যযুক্ত একক লাইনটি একক ফাইল হিসাবে গণনা করা অবিলম্বে সিল করা হয় এবং পরবর্তী লাইনে বাড়ানো যায় না।
জর্জেন স্ট্রোবেল

2
@ গেটসডিএ কেবলমাত্র আপনার প্রথম কোড স্নিপেটে কোনও বাগ নেই (স্পষ্টভাবে ক্লায়েন্টকে মানগুলি নির্ধারণ এবং সংজ্ঞায়িত করা প্রয়োজন। আপনার দ্বিতীয় এবং তৃতীয় উভয় সমাধানই আমার সর্বশেষ মন্তব্যে বর্ণিত সূক্ষ্ম বাগ রয়েছে (যদি ক্লায়েন্ট মুদ্রায় অ্যাক্সেস করতে দেখা দেয় তবে .GBP সরাসরি এবং প্রথমত, মান তালিকা "অর্ডার অফ আউট" হবে) আমি স্কালার গণনা ডোমেনটি ব্যাপকভাবে অনুসন্ধান করেছি এবং আমার এই একই থ্রেডের উত্তরে এটি বিস্তারিতভাবে বর্ণনা করেছি: stackoverflow.com/a/25923651/501113
বিশৃঙ্খল

1
সম্ভবত এই পদ্ধতির একটি অপূর্ণতা (যাইহোক জাভা এনামগুলির তুলনায়) হ'ল আপনি যখন আইডিইতে মুদ্রা <ডট> টাইপ করেন তখন এটি উপলব্ধ বিকল্পগুলি দেখায় না show
ইভান বালাসভ

1
@ সেবসেসব্রন ​​যেমন উল্লেখ করেছেন, কেস অবজেক্টগুলি এখানে অলস। সুতরাং আমি যদি কল করি তবে আমি Currency.valuesকেবল পূর্বে অ্যাক্সেস করা মানগুলি ফিরে পাই। যে প্রায় কোনো উপায় আছে কি?
সাসগোরিলা

27

গণনার উপর কেস ক্লাস ব্যবহারের সুবিধাগুলি হ'ল:

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

কেস ক্লাসের পরিবর্তে এনুমারেশন ব্যবহারের সুবিধাগুলি হ'ল:

  • অঙ্কগুলি সাধারণত লেখার জন্য কিছুটা কম কোড হবে।
  • স্ক্যালায় নতুন কারও জন্য এটি বিবেচনা করা একটু সহজ, যেহেতু সেগুলি অন্য ভাষায় প্রচলিত

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


15

আপডেট: নীচের কোডটিতে এখানে বাগ বর্ণিত একটি বাগ রয়েছে । নীচের পরীক্ষার প্রোগ্রামটি কাজ করে, তবে আপনি যদি DayOfWeek.Mon (উদাহরণস্বরূপ) ডেওআফউইকের আগে ব্যবহার করেন তবে এটি ব্যর্থ হবে কারণ ডায়ওফউইক আরম্ভ করা হয়নি (কোনও অভ্যন্তরীণ বস্তুর ব্যবহারের ফলে কোনও বাহ্যিক বস্তু আরম্ভের কারণ হয় না)। আপনি এখনও আপনার কোডটি ব্যবহার করতে পারেন যদি আপনি val enums = Seq( DayOfWeek )আপনার প্রধান শ্রেণীর মতো কিছু করেন, আপনার এনামগুলি শুরু করার জন্য জোর করে, বা আপনি বিশৃঙ্খল 3 কিলিব্রিয়ামের পরিবর্তনগুলি ব্যবহার করতে পারেন। ম্যাক্রো-ভিত্তিক এনামের প্রত্যাশায়!


তুমি যদি চাও

  • অ-বহনযোগ্য প্যাটার্ন মেলে সম্পর্কে সতর্কতা
  • প্রতিটি এনাম মান হিসাবে নির্ধারিত একটি আইটি আইডি, যা আপনি allyচ্ছিকভাবে নিয়ন্ত্রণ করতে পারেন
  • এনাম মানগুলির একটি অপরিবর্তনীয় তালিকা, ক্রম হিসাবে সেগুলি সংজ্ঞায়িত করা হয়েছিল
  • নাম থেকে এনাম মান পর্যন্ত একটি অপরিবর্তনীয় মানচিত্র
  • মান থেকে আইম থেকে একটি অপরিবর্তনীয় মানচিত্র
  • সমস্ত বা নির্দিষ্ট এনুম মানগুলির জন্য বা সামগ্রিকভাবে এনুমের জন্য পদ্ধতি / ডেটা স্টিক করার জায়গা
  • অর্ডার করা এনাম মানগুলি (যাতে আপনি পরীক্ষা করতে পারেন, উদাহরণস্বরূপ, দিন <বুধবার)
  • অন্যকে তৈরি করতে একটি এনাম বাড়ানোর ক্ষমতা

তাহলে নিম্নলিখিতগুলি আগ্রহী হতে পারে। মতামত স্বাগত।

এই বাস্তবায়নে এনস্ট্রাক্ট এনুম এবং এনামওয়াল বেস ক্লাস রয়েছে, যা আপনি প্রসারিত করেছেন। আমরা এক মিনিটের মধ্যে এই ক্লাসগুলি দেখতে পাব, তবে প্রথমে আপনি এখানে একটি এনাম সংজ্ঞা দেবেন তা এখানে:

object DayOfWeek extends Enum {
  sealed abstract class Val extends EnumVal
  case object Mon extends Val; Mon()
  case object Tue extends Val; Tue()
  case object Wed extends Val; Wed()
  case object Thu extends Val; Thu()
  case object Fri extends Val; Fri()
  case object Sat extends Val; Sat()
  case object Sun extends Val; Sun()
}

নোট করুন যে এটিকে প্রাণবন্ত করতে আপনাকে প্রতিটি এনাম মান ব্যবহার করতে হবে (এর প্রয়োগ পদ্ধতিটি কল করুন)। [আমি আশা করি অভ্যন্তরীণ জিনিসগুলি অলস না হলে আমি বিশেষভাবে সেগুলি না করার জন্য বলি। আমি মনে করি.]

আমরা অবশ্যই চাইলে DayOfWeek, Val, বা স্বতন্ত্র কেস অবজেক্টগুলিতে পদ্ধতি / ডেটা যুক্ত করতে পারি।

এবং আপনি এখানে যেমন একটি এনাম ব্যবহার করবেন তা এখানে:

object DayOfWeekTest extends App {

  // To get a map from Int id to enum:
  println( DayOfWeek.valuesById )

  // To get a map from String name to enum:
  println( DayOfWeek.valuesByName )

  // To iterate through a list of the enum values in definition order,
  // which can be made different from ID order, and get their IDs and names:
  DayOfWeek.values foreach { v => println( v.id + " = " + v ) }

  // To sort by ID or name:
  println( DayOfWeek.values.sorted mkString ", " )
  println( DayOfWeek.values.sortBy(_.toString) mkString ", " )

  // To look up enum values by name:
  println( DayOfWeek("Tue") ) // Some[DayOfWeek.Val]
  println( DayOfWeek("Xyz") ) // None

  // To look up enum values by id:
  println( DayOfWeek(3) )         // Some[DayOfWeek.Val]
  println( DayOfWeek(9) )         // None

  import DayOfWeek._

  // To compare enums as ordinals:
  println( Tue < Fri )

  // Warnings about non-exhaustive pattern matches:
  def aufDeutsch( day: DayOfWeek.Val ) = day match {
    case Mon => "Montag"
    case Tue => "Dienstag"
    case Wed => "Mittwoch"
    case Thu => "Donnerstag"
    case Fri => "Freitag"
 // Commenting these out causes compiler warning: "match is not exhaustive!"
 // case Sat => "Samstag"
 // case Sun => "Sonntag"
  }

}

এটি সংকলন করার পরে আপনি যা পান তা এখানে:

DayOfWeekTest.scala:31: warning: match is not exhaustive!
missing combination            Sat
missing combination            Sun

  def aufDeutsch( day: DayOfWeek.Val ) = day match {
                                         ^
one warning found

আপনি "(দিন: @ চেক করা) ম্যাচ" এর সাথে "ডে ম্যাচ" প্রতিস্থাপন করতে পারেন যেখানে আপনি এই ধরনের সতর্কতা চান না বা শেষে কেবল ক্যাচ-অল কেস অন্তর্ভুক্ত করতে পারেন।

আপনি যখন উপরের প্রোগ্রামটি চালান, আপনি এই আউটপুটটি পান:

Map(0 -> Mon, 5 -> Sat, 1 -> Tue, 6 -> Sun, 2 -> Wed, 3 -> Thu, 4 -> Fri)
Map(Thu -> Thu, Sat -> Sat, Tue -> Tue, Sun -> Sun, Mon -> Mon, Wed -> Wed, Fri -> Fri)
0 = Mon
1 = Tue
2 = Wed
3 = Thu
4 = Fri
5 = Sat
6 = Sun
Mon, Tue, Wed, Thu, Fri, Sat, Sun
Fri, Mon, Sat, Sun, Thu, Tue, Wed
Some(Tue)
None
Some(Thu)
None
true

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

এখানে নিজেই এনাম ক্লাস (এবং এর মধ্যে এনামওয়াল) রয়েছে:

abstract class Enum {

  type Val <: EnumVal

  protected var nextId: Int = 0

  private var values_       =       List[Val]()
  private var valuesById_   = Map[Int   ,Val]()
  private var valuesByName_ = Map[String,Val]()

  def values       = values_
  def valuesById   = valuesById_
  def valuesByName = valuesByName_

  def apply( id  : Int    ) = valuesById  .get(id  )  // Some|None
  def apply( name: String ) = valuesByName.get(name)  // Some|None

  // Base class for enum values; it registers the value with the Enum.
  protected abstract class EnumVal extends Ordered[Val] {
    val theVal = this.asInstanceOf[Val]  // only extend EnumVal to Val
    val id = nextId
    def bumpId { nextId += 1 }
    def compare( that:Val ) = this.id - that.id
    def apply() {
      if ( valuesById_.get(id) != None )
        throw new Exception( "cannot init " + this + " enum value twice" )
      bumpId
      values_ ++= List(theVal)
      valuesById_   += ( id       -> theVal )
      valuesByName_ += ( toString -> theVal )
    }
  }

}

এবং এখানে এটির আরও উন্নত ব্যবহার রয়েছে যা আইডিগুলি নিয়ন্ত্রণ করে এবং ভাল অ্যাস্ট্রাকশন এবং এনামগুলিতে ডেটা / পদ্ধতি যুক্ত করে:

object DayOfWeek extends Enum {

  sealed abstract class Val( val isWeekday:Boolean = true ) extends EnumVal {
    def isWeekend = !isWeekday
    val abbrev = toString take 3
  }
  case object    Monday extends Val;    Monday()
  case object   Tuesday extends Val;   Tuesday()
  case object Wednesday extends Val; Wednesday()
  case object  Thursday extends Val;  Thursday()
  case object    Friday extends Val;    Friday()
  nextId = -2
  case object  Saturday extends Val(false); Saturday()
  case object    Sunday extends Val(false);   Sunday()

  val (weekDays,weekendDays) = values partition (_.isWeekday)
}

এটি সরবরাহ করার জন্য Tyvm। আমি সত্যিই এটার প্রশংসা করছি. যাইহোক, আমি লক্ষ্য করছি যে এটি ভাল এর বিপরীতে "var" ব্যবহার করছে। এবং এটি এফপি জগতে সীমান্তের মারাত্মক পাপ। সুতরাং, এর প্রয়োগের কোনও উপায় নেই যে এখানে ভের ব্যবহার নেই? এটি উত্সাহিত যদি এটি কোনও প্রকারের FP প্রান্তের কেস হয় এবং আমি বুঝতে পারি না যে আপনার বাস্তবায়নটি কীভাবে FP অবাঞ্ছিত।
বিশৃঙ্খলা3 কুইলিব্রিয়াম

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

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

@ বিশৃঙ্খলা3 কুইলিব্রিয়াম: বাহ! এটি অনুসরণ করার জন্য আপনাকে ধন্যবাদ, এবং অবশ্যই ভারী উত্তোলনের জন্য রেক্স কেরকে ধন্যবাদ। আমি এখানে সমস্যাটি উল্লেখ করব এবং আপনার তৈরি প্রশ্নটি উল্লেখ করব।
AmigoNico

"[ব্যবহার var] এফপি বিশ্বে একটি সীমান্তের মারাত্মক পাপ" - আমি মনে করি না যে মতামত সর্বজনস্বীকৃত।
এরিক কাপলুন

12

আমার এখানে একটি দুর্দান্ত সরল লাইব রয়েছে যা আপনাকে নিজের মূল্যবোধের নিজস্ব তালিকা বজায় না রেখে এনল মান হিসাবে সিল করা বৈশিষ্ট্য / শ্রেণি ব্যবহার করতে দেয় allows এটি একটি সাধারণ ম্যাক্রোর উপর নির্ভর করে যা বাগির উপর নির্ভর করে না knownDirectSubclasses

https://github.com/lloydmeta/enumeratum


10

মার্চ 2017 আপডেট করুন: অ্যান্টনি অ্যাকসিওলি দ্বারা মন্তব্য করা হিসাবে , scala.Enumeration/enumজনসংযোগ বন্ধ করে দেওয়া হয়েছে।

ডটি (স্কালার পরবর্তী প্রজন্মের সংকলক) নেতৃত্ব দেবে, যদিও ডটি ইস্যু 1970 এবং মার্টিন ওডারস্কির পিআর 1958


দ্রষ্টব্য: এখানে এখন (আগস্ট 2016, 6+ বছর পরে) অপসারণের একটি প্রস্তাব রয়েছে scala.Enumeration: PR 5352

হ্রাস করুন scala.Enumeration, @enumটীকা যুক্ত করুন

বাক্য গঠন

@enum
 class Toggle {
  ON
  OFF
 }

সম্ভাব্য বাস্তবায়ন উদাহরণ, উদ্দেশ্যটি হ'ল এডিটিগুলিকে সমর্থন করা যা নির্দিষ্ট সীমাবদ্ধতার সাথে মিল রাখে (কোনও নেস্টিং, পুনরাবৃত্তি বা কনস্ট্রাক্টরের বিভিন্ন পরামিতি নেই), যেমন:

@enum
sealed trait Toggle
case object ON  extends Toggle
case object OFF extends Toggle

নিরবচ্ছিন্ন বিপর্যয়টি হ্রাস করে scala.Enumeration

@ স্কেল ওভারের জন্য এনামের সুবিধা। গণনা:

  • আসলে কাজ করে
  • জাভা ইন্টারপ
  • মুছে ফেলার সমস্যা নেই
  • গণনার সংজ্ঞা দেওয়ার সময় কোন বিভ্রান্তিকর মিনি-ডিএসএল নয়

অসুবিধাগুলি: কোনওটিই নয়।

এটি স্কালা-জেভিএম সমর্থন করে এমন একটি কোডবেস না পাওয়ার Scala.jsএবং স্কালা-নেটিভ (জাভা উত্স কোড সমর্থিত নয় Scala.js/Scala-Native, স্কালা উত্স কোডটি স্ক্যালাল-জেভিএম-তে বিদ্যমান এপিআই দ্বারা স্বীকৃত এনামগুলি সংজ্ঞায়িত করতে সক্ষম নয়) ইস্যুটিকে সম্বোধন করে।


উপরের পিআর বন্ধ হয়েছে (আনন্দ নেই)। এটি এখন 2017 এবং দেখে মনে হচ্ছে ডটি অবশেষে একটি এনাম কনস্ট্রাক্ট পেতে চলেছে। এখানে সমস্যা এবং মার্টিনের পিআর । মার্জ, মার্জ, মার্জ!
অ্যান্থনি অ্যাকলিওলি

8

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

অন্য কথায়: "কেস ক্লাস সহ গণ্যমানের মোট সেটগুলির তালিকা পাওয়ার সহজ কোনও উপায় নেই"।


5

আপনি যদি অন্য জেভিএম ভাষা (যেমন জাভা) এর সাথে আন্তঃব্যবহারযোগ্যতা বজায় রাখার বিষয়ে গুরুতর হন তবে জাভা এনামগুলি লেখাই সবচেয়ে ভাল বিকল্প। যারা স্কালা এবং জাভা কোড উভয় থেকেই স্বচ্ছভাবে কাজ করে, যা scala.Enumerationবস্তুগুলির জন্য বা কেস এর চেয়ে বেশি বলা যায়। গিটহাবের প্রতিটি নতুন শখের প্রকল্পের জন্য একটি নতুন গণনার পাঠাগার না রাখি, যদি এড়ানো যায়!


4

আমি একটি কেস ক্লাস একটি গণনার নকল করার বিভিন্ন সংস্করণ দেখেছি। আমার সংস্করণটি এখানে:

trait CaseEnumValue {
    def name:String
}

trait CaseEnum {
    type V <: CaseEnumValue
    def values:List[V]
    def unapply(name:String):Option[String] = {
        if (values.exists(_.name == name)) Some(name) else None
    }
    def unapply(value:V):String = {
        return value.name
    }
    def apply(name:String):Option[V] = {
        values.find(_.name == name)
    }
}

যা আপনাকে নিম্নলিখিত শ্রেণীর মতো দেখতে কেস ক্লাসগুলি তৈরি করতে সহায়তা করে:

abstract class Currency(override name:String) extends CaseEnumValue {
}

object Currency extends CaseEnum {
    type V = Site
    case object EUR extends Currency("EUR")
    case object GBP extends Currency("GBP")
    var values = List(EUR, GBP)
}

আমার মতো তালিকায় প্রতিটি কেস ক্লাস যুক্ত করার চেয়ে কেউ হয়তো আরও ভাল কৌশল নিয়ে আসতে পারে। এই সময়ে আমি যা করতে পেরেছি এটিই ছিল।


কেন দুটি পৃথক প্রয়োগযোগ্য পদ্ধতি?
সাইশ

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

2

আমি এই দুটি অপশনটিতে শেষ বার যাবত তাদের প্রয়োজন হয়েছিল এবং পিছনে যাচ্ছি। সম্প্রতি অবধি, আমার পছন্দটি সিলড বৈশিষ্ট্য / কেস অবজেক্ট বিকল্পের জন্য।

1) স্কেল গণনা ঘোষণা

object OutboundMarketMakerEntryPointType extends Enumeration {
  type OutboundMarketMakerEntryPointType = Value

  val Alpha, Beta = Value
}

2) সিলযুক্ত বৈশিষ্ট্য + কেস অবজেক্টস

sealed trait OutboundMarketMakerEntryPointType

case object AlphaEntryPoint extends OutboundMarketMakerEntryPointType

case object BetaEntryPoint extends OutboundMarketMakerEntryPointType

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

স্কাল গণনা

পেশাদাররা: - বিকল্পের সাথে তাত্ক্ষণিকভাবে কাজ করার জন্য বা সরাসরি সঠিক ধরে নেওয়ার জন্য ক্রিয়াকলাপ (একটি ধ্রুবক স্টোর থেকে লোড করার সময় সহজ) - সমস্ত সম্ভাব্য মানগুলির মধ্যে অন্তর্ভুক্তি সমর্থিত

কনস: - অব্যক্ত অনুসন্ধানের জন্য সংকলন সতর্কতা সমর্থিত নয় (প্যাটার্নের সাথে মিলের তুলনাকে কম আদর্শ করে তোলে)

কেস অবজেক্টস / সিলযুক্ত বৈশিষ্ট্য

পেশাদাররা: - সিল করা বৈশিষ্টগুলি ব্যবহার করে আমরা কিছু মান প্রাক-ইনস্ট্যান্ট করতে পারি যখন অন্যরা সৃষ্টির সময় ইনজেকশনের ব্যবস্থা করতে পারে - প্যাটার্ন ম্যাচিংয়ের জন্য পুরো সমর্থন (প্রয়োগ / প্রয়োগযোগ্য প্রয়োগ না করা)

কনস: - একটি ধ্রুবক স্টোর থেকে বোঝা - আপনি প্রায়শই এখানে প্যাটার্ন মেলানো ব্যবহার করতে হবে বা আপনার সম্ভাব্য সমস্ত 'এনাম মান' এর নিজস্ব তালিকাটি নির্ধারণ করতে হবে

শেষ পর্যন্ত আমাকে আমার মতামত পরিবর্তন করার কারণটি হ'ল নীচের স্নিপেটের মতো:

object DbInstrumentQueries {
  def instrumentExtractor(tableAlias: String = "s")(rs: ResultSet): Instrument = {
    val symbol = rs.getString(tableAlias + ".name")
    val quoteCurrency = rs.getString(tableAlias + ".quote_currency")
    val fixRepresentation = rs.getString(tableAlias + ".fix_representation")
    val pointsValue = rs.getInt(tableAlias + ".points_value")
    val instrumentType = InstrumentType.fromString(rs.getString(tableAlias +".instrument_type"))
    val productType = ProductType.fromString(rs.getString(tableAlias + ".product_type"))

    Instrument(symbol, fixRepresentation, quoteCurrency, pointsValue, instrumentType, productType)
  }
}

object InstrumentType {
  def fromString(instrumentType: String): InstrumentType = Seq(CurrencyPair, Metal, CFD)
  .find(_.toString == instrumentType).get
}

object ProductType {

  def fromString(productType: String): ProductType = Seq(Commodity, Currency, Index)
  .find(_.toString == productType).get
}

.getকল অসহ্য ছিল - শুমার ব্যবহার পরিবর্তে আমি কেবল শুমার উপর withName পদ্ধতি কল করতে পারেন নিম্নরূপ:

object DbInstrumentQueries {
  def instrumentExtractor(tableAlias: String = "s")(rs: ResultSet): Instrument = {
    val symbol = rs.getString(tableAlias + ".name")
    val quoteCurrency = rs.getString(tableAlias + ".quote_currency")
    val fixRepresentation = rs.getString(tableAlias + ".fix_representation")
    val pointsValue = rs.getInt(tableAlias + ".points_value")
    val instrumentType = InstrumentType.withNameString(rs.getString(tableAlias + ".instrument_type"))
    val productType = ProductType.withName(rs.getString(tableAlias + ".product_type"))

    Instrument(symbol, fixRepresentation, quoteCurrency, pointsValue, instrumentType, productType)
  }
}

সুতরাং আমি মনে করি আমার অগ্রাধিকারটি অগ্রাধিকার হ'ল গণনাগুলি ব্যবহার করা যখন মানগুলি অন্যথায় কোনও সংগ্রহস্থল এবং কেস অবজেক্ট / সিল করা বৈশিষ্ট্যগুলি থেকে অ্যাক্সেস করার পরিকল্পনা করা হয়।


দ্বিতীয় কোড প্যাটার্নটি কীভাবে আকাঙ্ক্ষিত তা আমি দেখতে পাচ্ছি (প্রথম কোড প্যাটার্ন থেকে দুটি সহায়ক পদ্ধতি থেকে মুক্তি পেয়ে)। তবে, আমি এমন একটি উপায় খুঁজে পেয়েছি যাতে আপনি এই দুটি নিদর্শনগুলির মধ্যে বেছে নিতে বাধ্য হন না। : আমি উত্তরে সমগ্র ডোমেইন আমি এই থ্রেডে পোস্ট করেছেন আবরণ stackoverflow.com/a/25923651/501113
chaotic3quilibrium

2

আমি পছন্দ করি case objects (এটি ব্যক্তিগত পছন্দের বিষয়)। এই পদ্ধতির অন্তর্নিহিত সমস্যাগুলি মোকাবেলায় (সমস্ত উপাদানগুলির উপর পার্সিং স্ট্রিং এবং পুনরাবৃত্তি), আমি কয়েকটি লাইন যুক্ত করেছি যা নিখুঁত নয়, তবে কার্যকর।

এটি কোডটি কার্যকর হতে পারে এবং অন্যরাও এটির উন্নতি করতে পারে আশা করে আমি এখানে কোডটি আটক করছি।

/**
 * Enum for Genre. It contains the type, objects, elements set and parse method.
 *
 * This approach supports:
 *
 * - Pattern matching
 * - Parse from name
 * - Get all elements
 */
object Genre {
  sealed trait Genre

  case object MALE extends Genre
  case object FEMALE extends Genre

  val elements = Set (MALE, FEMALE) // You have to take care this set matches all objects

  def apply (code: String) =
    if (MALE.toString == code) MALE
    else if (FEMALE.toString == code) FEMALE
    else throw new IllegalArgumentException
}

/**
 * Enum usage (and tests).
 */
object GenreTest extends App {
  import Genre._

  val m1 = MALE
  val m2 = Genre ("MALE")

  assert (m1 == m2)
  assert (m1.toString == "MALE")

  val f1 = FEMALE
  val f2 = Genre ("FEMALE")

  assert (f1 == f2)
  assert (f1.toString == "FEMALE")

  try {
    Genre (null)
    assert (false)
  }
  catch {
    case e: IllegalArgumentException => assert (true)
  }

  try {
    Genre ("male")
    assert (false)
  }
  catch {
    case e: IllegalArgumentException => assert (true)
  }

  Genre.elements.foreach { println }
}

0

যারা এখনও গেটসডা-র কাজের কাজের উত্তর পেতে চান তা জন্য : আপনি কেস অবজেক্টটি এটি ইনস্ট্যান্ট করার ঘোষণা দেওয়ার পরে কেবল রেফারেন্স করতে পারেন:

trait Enum[A] {
  trait Value { self: A =>
    _values :+= this
  }
  private var _values = List.empty[A]
  def values = _values
}

sealed trait Currency extends Currency.Value
object Currency extends Enum[Currency] {
  case object EUR extends Currency; 
  EUR //THIS IS ONLY CHANGE
  case object GBP extends Currency; GBP //Inline looks better
}

0

আমি মনে করি case classesওভার করার সবচেয়ে বড় সুবিধাটি enumerationsহ'ল আপনি টাইপ ক্লাস প্যাটার্ন ওরফে অ্যাড-হক পলিমারফিজম ব্যবহার করতে পারেন । যেমন enums মেলে প্রয়োজন হবে না:

someEnum match {
  ENUMA => makeThis()
  ENUMB => makeThat()
}

পরিবর্তে আপনার মতো কিছু থাকবে:

def someCode[SomeCaseClass](implicit val maker: Maker[SomeCaseClass]){
  maker.make()
}

implicit val makerA = new Maker[CaseClassA]{
  def make() = ...
}
implicit val makerB = new Maker[CaseClassB]{
  def make() = ...
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.