স্কালায় গণনা বৃদ্ধি বা বনাম কেস ক্লাস (বা কেস অবজেক্টস) কখন ব্যবহার করবেন সে সম্পর্কে কোনও সেরা-অনুশীলনের গাইডলাইন রয়েছে ?
তারা একই সুবিধা বঞ্চিত বলে মনে হচ্ছে।
enum
(মধ্য 2020 জন্য)।
স্কালায় গণনা বৃদ্ধি বা বনাম কেস ক্লাস (বা কেস অবজেক্টস) কখন ব্যবহার করবেন সে সম্পর্কে কোনও সেরা-অনুশীলনের গাইডলাইন রয়েছে ?
তারা একই সুবিধা বঞ্চিত বলে মনে হচ্ছে।
enum
(মধ্য 2020 জন্য)।
উত্তর:
একটি বড় পার্থক্য হ'ল 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
এর :
"গণনা" এর সমস্ত দৃষ্টান্তে পুনরাবৃত্তি করতে পারে না । এটি অবশ্যই কেস, তবে আমি অনুশীলনে এটি অত্যন্ত বিরল বলে মনে করেছি যে এটি প্রয়োজনীয়।
স্থির মান থেকে সহজেই ইনস্ট্যান্ট করতে পারে না । এটিও সত্য তবে বিশাল অঙ্কের ক্ষেত্রে (উদাহরণস্বরূপ, সমস্ত মুদ্রা) বাদে এটি একটি বিশাল ওভারহেড উপস্থাপন করে না।
trade.ccy
সিল করা বৈশিষ্ট উদাহরণে আইটেমটির ধরণটি কীভাবে মিলছে তা আমি বুঝতে পারি না ।
case
object
এর চেয়ে বড় (x 4x) কোডের পদাঙ্কগুলি জেনারেট করে না Enumeration
? বিশেষত scala.js
ছোট পদক্ষেপের প্রয়োজন এমন প্রকল্পগুলির জন্য দরকারী পার্থক্য ।
আপডেট: একটি নতুন ম্যাক্রো ভিত্তিক সমাধান তৈরি করা হয়েছে যা নীচের রূপরেখার সমাধানের তুলনায় অনেক বেশি উন্নত। আমি দৃ new ়ভাবে এই নতুন ম্যাক্রো ভিত্তিক সমাধান ব্যবহার করার পরামর্শ দিচ্ছি । এবং মনে হয় ডটিটির পরিকল্পনাগুলি এই শৈলীর এনাম সলিউশনটিকে ভাষার অংশ হিসাবে তৈরি করবে। Whoohoo!
সংক্ষিপ্তসার: স্কালার একটি প্রকল্পের মধ্যে
জাভা পুনরুত্পাদন করার চেষ্টা করার জন্য তিনটি প্রাথমিক নিদর্শন রয়েছে Enum
। তিনটি নিদর্শনগুলির মধ্যে দুটি; সরাসরি জাভা ব্যবহার করে Enum
এবং scala.Enumeration
, স্কালার বিস্তৃত প্যাটার্ন মেলানো সক্ষম করতে সক্ষম নয়। এবং তৃতীয়টি; "সিলড বৈশিষ্ট্য + কেস অবজেক্ট", করে ... তবে জেভিএম শ্রেণি / অবজেক্টের সূচনা জটিলতা রয়েছে যার ফলে বেমানান অর্ডিনাল সূচক তৈরি হয়।
আমি দুটি ক্লাস নিয়ে একটি সমাধান তৈরি করেছি; গণনা এবং গণনা ডেকোর্টেড , এই গিস্টে অবস্থিত । আমি এই থ্রেডে কোডটি পোস্ট করিনি কারণ গণনার জন্য ফাইলটি বেশ বড় (+400 লাইন - বাস্তবায়নের প্রসঙ্গে ব্যাখ্যা করার জন্য প্রচুর মন্তব্য রয়েছে)।
বিশদ:
আপনি যে প্রশ্নটি জিজ্ঞাসা করছেন তা বেশ সাধারণ; "... বর্ধিত case
ক্লাস কখন ব্যবহার করবেনobjects
[scala.]Enumeration
"। এবং এটিতে দেখা যাচ্ছে যে অনেকগুলি সম্ভাব্য উত্তর রয়েছে, প্রতিটি উত্তর আপনার নির্দিষ্ট প্রকল্পের প্রয়োজনীয়তার সূক্ষ্মতার উপর নির্ভর করে। উত্তরটি তিনটি বেসিক নিদর্শনকে কমিয়ে আনা যায়।
শুরু করার জন্য, আসুন নিশ্চিত করা যাক আমরা একটি গণনা কী তা একই বুনিয়াদি ধারণা থেকে কাজ করছি। আসুন Enum
জাভা 5 (1.5) হিসাবে প্রদত্ত শর্তাবলী মূলত একটি গণনা সংজ্ঞায়িত করা যাক :
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;
}
}
গণনা সংজ্ঞা থেকে নিম্নলিখিত আইটেমগুলি উপলভ্য নয়:
আমার বর্তমান প্রকল্পগুলির জন্য, স্কালা / জাভা মিশ্র প্রকল্পের পথের আশেপাশে ঝুঁকি নেওয়ার সুবিধা আমার নেই। এমনকি আমি যদি একটি মিশ্র প্রকল্পটি বেছে নিতে পারি, আইটেম আমাকে / যখন আমি হয় গণনা সদস্যদের যুক্ত / সরিয়ে ফেলা, বা বিদ্যমান গণনা সদস্যদের সাথে ডিল করার জন্য কিছু নতুন কোড লিখছি তখন আমাকে সংকলনের সময় সমস্যাগুলি ধরার অনুমতি দেওয়ার জন্য গুরুত্বপূর্ণ।
খ) " 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}
}
গণনা সংজ্ঞা থেকে নিম্নলিখিত আইটেমগুলি উপলভ্য নয়:
এটি বিতর্কযুক্ত এটি সত্যই গণনা সংজ্ঞা আইটেম 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]
}
গণনা সংজ্ঞা থেকে নিম্নলিখিত আইটেমগুলি উপলভ্য নয় (সরাসরি জাভা এনাম ব্যবহারের জন্য তালিকার সাথে অভিন্ন বলে মনে হচ্ছে):
আবার আমার বর্তমান প্রকল্পগুলির জন্য, আইটেম 7 আমাকে সংকলনের সদস্যদের যুক্ত / সরিয়ে ফেলা বা বিদ্যমান গণনা সদস্যদের সাথে ডিল করার জন্য কিছু নতুন কোড লিখতে থাকলে / আমাকে সংকলিত সময়ের সমস্যাগুলি ধরার অনুমতি দেওয়ার জন্য গুরুত্বপূর্ণ।
সুতরাং, একটি গণনার উপরোক্ত সংজ্ঞা দেওয়া, উপরের তিনটি সমাধানের মধ্যে কোনওটিই কাজ করে না কারণ তারা উপরের গণনার সংজ্ঞায় বর্ণিত সমস্ত কিছুই সরবরাহ করে না:
এর প্রতিটি সমাধানের অবশেষে প্রত্যেকে নিখোঁজ হওয়া প্রয়োজনীয়তার কিছু আবরণ করার চেষ্টা করার জন্য পুনর্নির্মাণ / প্রসারিত / রিফ্যাক্টর করা যেতে পারে। যাইহোক, জাভা 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
উপরের উদাহরণে)। আমি যখন এটি একক পুনরাবৃত্তিতে হ্রাস করেছি, তখনও দুটি সমস্যার কারণে কীভাবে এটি আরও কম করা যায় তা আমি দেখতে পেলাম না:
getClass.getDeclaredClasses
একটি অপরিজ্ঞাত অর্ডার রয়েছে (এবং case object
উত্স কোডে ঘোষণাপত্রের মতো একই ক্রমে হওয়ার সম্ভাবনা খুব কম )এই দুটি ইস্যু দেওয়া, আমি একটি অন্তর্নিহিত আদেশ জেনারেট করার চেষ্টা ছেড়ে দিতে হয়েছিল এবং ক্লায়েন্টের স্পষ্টরূপে সংজ্ঞায়িত হয়ে নির্দিষ্ট ধরণের ধারণার সাথে এটি ঘোষণা করতে হয়েছিল। যেহেতু স্কালার সংগ্রহগুলিতে একটি সন্নিবেশিত অর্ডার সেট প্রয়োগকরণ নেই, তাই আমি সবচেয়ে ভাল করতে পেরেছিলাম List
এবং তারপরে রানটাইম যাচাই করেছিলাম এটি সত্যই একটি সেট was এটি কীভাবে আমি এটি অর্জন করতে পছন্দ করতাম তা নয়।
এবং নকশার জন্য এই দ্বিতীয় তালিকা / সেট ক্রমটি প্রয়োজনীয় প্রয়োজন val
, ChessPiecesEnhancedDecorated
উপরের উদাহরণটি দেওয়া হয়েছে , এটি যুক্ত করা সম্ভব হয়েছিল case object PAWN2 extends Member
এবং তারপরে যুক্ত Decoration(PAWN2,'P2', 2)
করতে ভুলে গিয়েছিল decorationOrderedSet
। সুতরাং, তালিকাটি কেবলমাত্র একটি সেট নয় তা যাচাই করার জন্য একটি রানটাইম চেক আছে, তবে এতে কেস অবজেক্টের সমস্ত রয়েছে যা প্রসারিত করে sealed trait Member
। এটি কাজ করার জন্য প্রতিবিম্ব / ম্যাক্রো হেলকের একটি বিশেষ রূপ ছিল।
মন্তব্য এবং / অথবা গিস্ট উপর প্রতিক্রিয়া দয়া করে ।
org.scalaolio.util.Enumeration
এবং org.scalaolio.util.EnumerationDecorated
: scalaolio.org
কেস অবজেক্টগুলি তাদের স্ট্রিং পদ্ধতির জন্য ইতিমধ্যে তাদের নামটি ফিরিয়ে দেয়, তাই এটি আলাদাভাবে পাস করা অপ্রয়োজনীয়। এখানে ঝো'র অনুরূপ একটি সংস্করণ রয়েছে (ব্রেভিটির জন্য সুবিধাগুলি বাদ দেওয়া):
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
Currency.values
কেবল পূর্বে অ্যাক্সেস করা মানগুলি ফিরে পাই। যে প্রায় কোনো উপায় আছে কি?
গণনার উপর কেস ক্লাস ব্যবহারের সুবিধাগুলি হ'ল:
কেস ক্লাসের পরিবর্তে এনুমারেশন ব্যবহারের সুবিধাগুলি হ'ল:
সুতরাং সাধারণভাবে, আপনার যদি কেবল নাম অনুসারে সাধারণ ধ্রুবকগুলির একটি তালিকা প্রয়োজন হয়, তবে গণনাগুলি ব্যবহার করুন। অন্যথায়, আপনার যদি আরও কিছু জটিল জটিল প্রয়োজন হয় বা আপনার সমস্ত ম্যাচ নির্দিষ্ট করা আছে কিনা তা জানানোর সংকলকটির অতিরিক্ত সুরক্ষা চান তবে কেস ক্লাস ব্যবহার করুন।
আপডেট: নীচের কোডটিতে এখানে বাগ বর্ণিত একটি বাগ রয়েছে । নীচের পরীক্ষার প্রোগ্রামটি কাজ করে, তবে আপনি যদি DayOfWeek.Mon (উদাহরণস্বরূপ) ডেওআফউইকের আগে ব্যবহার করেন তবে এটি ব্যর্থ হবে কারণ ডায়ওফউইক আরম্ভ করা হয়নি (কোনও অভ্যন্তরীণ বস্তুর ব্যবহারের ফলে কোনও বাহ্যিক বস্তু আরম্ভের কারণ হয় না)। আপনি এখনও আপনার কোডটি ব্যবহার করতে পারেন যদি আপনি val enums = Seq( DayOfWeek )
আপনার প্রধান শ্রেণীর মতো কিছু করেন, আপনার এনামগুলি শুরু করার জন্য জোর করে, বা আপনি বিশৃঙ্খল 3 কিলিব্রিয়ামের পরিবর্তনগুলি ব্যবহার করতে পারেন। ম্যাক্রো-ভিত্তিক এনামের প্রত্যাশায়!
তুমি যদি চাও
তাহলে নিম্নলিখিতগুলি আগ্রহী হতে পারে। মতামত স্বাগত।
এই বাস্তবায়নে এনস্ট্রাক্ট এনুম এবং এনামওয়াল বেস ক্লাস রয়েছে, যা আপনি প্রসারিত করেছেন। আমরা এক মিনিটের মধ্যে এই ক্লাসগুলি দেখতে পাব, তবে প্রথমে আপনি এখানে একটি এনাম সংজ্ঞা দেবেন তা এখানে:
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)
}
var
] এফপি বিশ্বে একটি সীমান্তের মারাত্মক পাপ" - আমি মনে করি না যে মতামত সর্বজনস্বীকৃত।
আমার এখানে একটি দুর্দান্ত সরল লাইব রয়েছে যা আপনাকে নিজের মূল্যবোধের নিজস্ব তালিকা বজায় না রেখে এনল মান হিসাবে সিল করা বৈশিষ্ট্য / শ্রেণি ব্যবহার করতে দেয় allows এটি একটি সাধারণ ম্যাক্রোর উপর নির্ভর করে যা বাগির উপর নির্ভর করে না knownDirectSubclasses
।
মার্চ 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
, স্কালা উত্স কোডটি স্ক্যালাল-জেভিএম-তে বিদ্যমান এপিআই দ্বারা স্বীকৃত এনামগুলি সংজ্ঞায়িত করতে সক্ষম নয়) ইস্যুটিকে সম্বোধন করে।
আপনি যখন পুনরাবৃত্তি করতে বা সমস্ত দৃষ্টান্তে ফিল্টার করতে হবে তখন ক্ষেত্রে শ্রেণি বনাম গণনার আর একটি অসুবিধা। এটি গণনার একটি অন্তর্নির্মিত ক্ষমতা (এবং পাশাপাশি জাভা এনামগুলি) যখন কেস ক্লাসগুলি স্বয়ংক্রিয়ভাবে এ জাতীয় ক্ষমতা সমর্থন করে না।
অন্য কথায়: "কেস ক্লাস সহ গণ্যমানের মোট সেটগুলির তালিকা পাওয়ার সহজ কোনও উপায় নেই"।
আপনি যদি অন্য জেভিএম ভাষা (যেমন জাভা) এর সাথে আন্তঃব্যবহারযোগ্যতা বজায় রাখার বিষয়ে গুরুতর হন তবে জাভা এনামগুলি লেখাই সবচেয়ে ভাল বিকল্প। যারা স্কালা এবং জাভা কোড উভয় থেকেই স্বচ্ছভাবে কাজ করে, যা scala.Enumeration
বস্তুগুলির জন্য বা কেস এর চেয়ে বেশি বলা যায়। গিটহাবের প্রতিটি নতুন শখের প্রকল্পের জন্য একটি নতুন গণনার পাঠাগার না রাখি, যদি এড়ানো যায়!
আমি একটি কেস ক্লাস একটি গণনার নকল করার বিভিন্ন সংস্করণ দেখেছি। আমার সংস্করণটি এখানে:
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)
}
আমার মতো তালিকায় প্রতিটি কেস ক্লাস যুক্ত করার চেয়ে কেউ হয়তো আরও ভাল কৌশল নিয়ে আসতে পারে। এই সময়ে আমি যা করতে পেরেছি এটিই ছিল।
আমি এই দুটি অপশনটিতে শেষ বার যাবত তাদের প্রয়োজন হয়েছিল এবং পিছনে যাচ্ছি। সম্প্রতি অবধি, আমার পছন্দটি সিলড বৈশিষ্ট্য / কেস অবজেক্ট বিকল্পের জন্য।
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)
}
}
সুতরাং আমি মনে করি আমার অগ্রাধিকারটি অগ্রাধিকার হ'ল গণনাগুলি ব্যবহার করা যখন মানগুলি অন্যথায় কোনও সংগ্রহস্থল এবং কেস অবজেক্ট / সিল করা বৈশিষ্ট্যগুলি থেকে অ্যাক্সেস করার পরিকল্পনা করা হয়।
আমি পছন্দ করি 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 }
}
যারা এখনও গেটসডা-র কাজের কাজের উত্তর পেতে চান তা জন্য : আপনি কেস অবজেক্টটি এটি ইনস্ট্যান্ট করার ঘোষণা দেওয়ার পরে কেবল রেফারেন্স করতে পারেন:
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
}
আমি মনে করি 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() = ...
}