এমন পরিস্থিতি রয়েছে যেখানে আপনার নন-কেস ক্লাস পছন্দ করা উচিত?
মার্টিন ওডারস্কি আমাদের স্ক্যালায় ফাংশনাল প্রোগ্রামিং নীতিমালা (লেকচার 4.6 - প্যাটার্ন ম্যাচিং) এর একটি ভাল সূচনা পয়েন্ট দিয়েছেন যা আমরা যখন ক্লাস এবং কেস ক্লাসের মধ্যে বেছে নিতে পারি তখন আমরা ব্যবহার করতে পারি। উদাহরণ অনুসারে স্কালার 7 তম অধ্যায়ে একই উদাহরণ রয়েছে।
বলুন, আমরা গাণিতিক প্রকাশের জন্য একটি দোভাষী লিখতে চাই। শুরুতে জিনিসগুলি সহজ রাখতে, আমরা কেবলমাত্র সংখ্যা এবং + ক্রিয়াকলাপের মধ্যে সীমাবদ্ধ করি। এই জাতীয় এক্সপ্রেশনগুলি শ্রেণীর শ্রেণিবিন্যাস হিসাবে উপস্থাপন করা যেতে পারে, মূল হিসাবে একটি বিমূর্ত বেস শ্রেণি এক্সপ্রেস এবং দুটি উপশ্রেন সংখ্যা এবং যোগফল। তারপরে, একটি অভিব্যক্তি 1 + (3 + 7) হিসাবে উপস্থাপিত হবে
নতুন যোগফল (নতুন সংখ্যা (1), নতুন যোগফল (নতুন সংখ্যা (3), নতুন সংখ্যা (7))
abstract class Expr {
def eval: Int
}
class Number(n: Int) extends Expr {
def eval: Int = n
}
class Sum(e1: Expr, e2: Expr) extends Expr {
def eval: Int = e1.eval + e2.eval
}
তদুপরি, একটি নতুন প্রোড ক্লাস যুক্ত করা বিদ্যমান কোডে কোনও পরিবর্তন প্রেরণা দেয় না:
class Prod(e1: Expr, e2: Expr) extends Expr {
def eval: Int = e1.eval * e2.eval
}
বিপরীতে, একটি নতুন পদ্ধতি যুক্ত করতে সমস্ত বিদ্যমান ক্লাসগুলির সংশোধন প্রয়োজন।
abstract class Expr {
def eval: Int
def print
}
class Number(n: Int) extends Expr {
def eval: Int = n
def print { Console.print(n) }
}
class Sum(e1: Expr, e2: Expr) extends Expr {
def eval: Int = e1.eval + e2.eval
def print {
Console.print("(")
print(e1)
Console.print("+")
print(e2)
Console.print(")")
}
}
কেস ক্লাসগুলির সাথে একই সমস্যা সমাধান করা।
abstract class Expr {
def eval: Int = this match {
case Number(n) => n
case Sum(e1, e2) => e1.eval + e2.eval
}
}
case class Number(n: Int) extends Expr
case class Sum(e1: Expr, e2: Expr) extends Expr
একটি নতুন পদ্ধতি যুক্ত করা একটি স্থানীয় পরিবর্তন।
abstract class Expr {
def eval: Int = this match {
case Number(n) => n
case Sum(e1, e2) => e1.eval + e2.eval
}
def print = this match {
case Number(n) => Console.print(n)
case Sum(e1,e2) => {
Console.print("(")
print(e1)
Console.print("+")
print(e2)
Console.print(")")
}
}
}
একটি নতুন প্রোড ক্লাস যুক্ত করার জন্য সমস্ত প্যাটার্নের মিলটি সম্ভাব্যভাবে পরিবর্তনের প্রয়োজন।
abstract class Expr {
def eval: Int = this match {
case Number(n) => n
case Sum(e1, e2) => e1.eval + e2.eval
case Prod(e1,e2) => e1.eval * e2.eval
}
def print = this match {
case Number(n) => Console.print(n)
case Sum(e1,e2) => {
Console.print("(")
print(e1)
Console.print("+")
print(e2)
Console.print(")")
}
case Prod(e1,e2) => ...
}
}
ভিডিও চিত্র থেকে প্রতিলিপি 4.6 প্যাটার্ন ম্যাচিং
এই উভয় ডিজাইনই পুরোপুরি সূক্ষ্ম এবং এগুলির মধ্যে পছন্দগুলি কখনও কখনও শৈলীর বিষয় হয় তবে এরপরেও কিছু মানদণ্ড রয়েছে যা গুরুত্বপূর্ণ।
একটি মানদণ্ড হতে পারে, আপনি কি প্রায়শই প্রকাশের নতুন উপ-শ্রেণী তৈরি করছেন বা আপনি প্রায়শই নতুন পদ্ধতি তৈরি করছেন? সুতরাং এটি একটি মানদণ্ড যা ভবিষ্যতের এক্সটেনসিবিলিটি এবং আপনার সিস্টেমের সম্ভাব্য এক্সটেনশন পাসের দিকে নজর দেয়।
আপনি যা করেন তা বেশিরভাগ ক্ষেত্রেই নতুন সাবক্লাস তৈরি করা হয়, তবে আসলে অবজেক্ট অরিয়েন্টেড পচন সমাধানের উপরের হাত রয়েছে। কারণটি হ'ল এটি খুব সহজ এবং একটি স্থানীয় পরিবর্তন কেবল একটি বাতাল পদ্ধতিতে একটি নতুন সাবক্লাস তৈরি করা , যেখানে কার্যকরী সমাধান হিসাবে, আপনাকে ফিরে যেতে হবে এবং এওল পদ্ধতিটির কোডটি পরিবর্তন করতে হবে এবং একটি নতুন কেস যুক্ত করতে হবে এটা।
অন্যদিকে, আপনি যা করেন তা প্রচুর নতুন পদ্ধতি তৈরি করে, তবে শ্রেণি শ্রেণিবিন্যাস নিজেই তুলনামূলকভাবে স্থিতিশীল রাখা হবে, তবে প্যাটার্ন মিলটি আসলে সুবিধাজনক। কারণ, আবার, প্যাটার্ন মিলের সমাধানের প্রতিটি নতুন পদ্ধতি হ'ল স্থানীয় পরিবর্তন , আপনি এটি বেস শ্রেণিতে রেখেছেন বা শ্রেণীর শ্রেণিবদ্ধের বাইরেও। বস্তুমুখী ক্ষয় হিসাবে শোয়ের মতো একটি নতুন পদ্ধতিতে প্রতিটি উপ শ্রেণীর জন্য একটি নতুন বৃদ্ধি প্রয়োজন। সুতরাং আরও কিছু অংশ থাকবে, আপনাকে স্পর্শ করতে হবে।
সুতরাং এই এক্সটেনসিবিলিটির সমস্যাটি দুটি মাত্রায়, যেখানে আপনি একটি শ্রেণিবিন্যাসে নতুন ক্লাস যুক্ত করতে চাইতে পারেন বা আপনি নতুন পদ্ধতি যুক্ত করতে চাইতে পারেন বা উভয়ই হতে পারে অভিব্যক্তির সমস্যা হিসাবে ।
মনে রাখবেন: আমাদের অবশ্যই এটি একটি প্রাথমিক পয়েন্টের মতো ব্যবহার করতে হবে, কেবলমাত্র মানদণ্ডের মতো নয়।