کلاس های مهر و موم
Kotlin Sealed Class
از کلاسهای Sealed زمانی استفاده میشود که هنگام ساخت زیرکلاس تنها محدود به موارد مشخصی باشیم.
1 2 3 4 5 6 7 8 9 10 | class Expr class Const(val value: Int) : Expr class Sum(val left: Expr, val right: Expr) : Expr fun eval(e: Expr): Int = when (e) { is Const -> e.value is Sum -> eval(e.right) + eval(e.left) else -> throw IllegalArgumentException("Unknown expression") } |
کلاس پایه Expr حاوی دو کلاس مشتق Const (نشانگر اعداد) و Sum (نشانگر مجموع دو عبارت) است. اینجا ناچاریم برای شرایط پیشفرضِ else در عبارت when از else استفاده کنیم. حالا اگر کلاس جدیدی از کلاس Expr مشتق کنیم، کامپایلر بخش else را تشخیص نداده و باگ بالقوهای داخل کد باقی میماند. بهتر بود کامپایلر در چنین شرایطی یعنی وقتی کلاس مشتق میکنیم خطای مناسبی صادر کند. برای حل این مشکل میتوانیم از کلاسهای Sealed استفاده کنیم. همانطور که در ابتدا گفتم، کلاسهای Sealed ساخت subclassها را با محدودیتهایی اجباری همراه میکنند. بنابراین هنگامی که تمام زیرکلاسها یک کلاس Sealed را داخل عبارت when هندل شود، دیگر نیازی به قسمت else نیست.
برای ساخت یک کلاس Sealed از مودیفایر Sealed استفاده میکنیم:
1 | sealed class Expr |
مثالی از کلاسهای Sealed در کاتلین
کد بالا، بدون مشکلات قبلی:
1 2 3 4 5 6 7 8 9 10 | sealed class Expr class Const(val value: Int) : Expr() class Sum(val left: Expr, val right: Expr) : Expr() object NotANumber : Expr() fun eval(e: Expr): Int = when (e) { is Const -> e.value is Sum -> eval(e.right) + eval(e.left) NotANumber -> java.lang.Double.NaN } |
همانطور که میبینید خبری از else نیست. اگر کلاس جدیدی از Expr مشتق کنید، کامپایلر خطا میدهد مگر در when هندلش کرده باشید.
چند نکته مهم:
- تمام زیرکلاسهای یک کلاس Sealed بایستی در یک فایل یکسان – یعنی همانجایی که کلاس Sealed تعریف شده – تعریف شوند؛
- کلاسهای Sealed به صورت پیشفرض abstract هستند، بنابراین نمیتوانید از رویشان نمونهسازی کنید؛
- شما نمیتوانید سازنده غیر خصوصی برای کلاسهای Sealed ایجاد نمایید؛ سازندهها به صورت پیشفرض private یا خصوصی هستند.
فرق بین Enum و کلاسهای Sealed
کلاس Enum و Sealed بسیار مشابه هم هستند. مقادیر نوع Enum نیز همانند کلاس Sealed محدود به موارد تعیین شده است. تنها فرقشان این است که Enum فقط میتواند یک نمونه داشته باشد در حالی که زیرکلاسهای یک کلاس Sealed میتوانند چندین نمونه داشته باشند.
Kotlin Sealed Class Kotlin Sealed Class Kotlin Sealed Class Kotlin Sealed Class Kotlin Sealed Class Kotlin Sealed Class