کلاس های مهر و موم شده جاوا و تطبیق الگوی جامع
آدرس مقاله: https://neilmadden.blog/2026/04/24/java-sealed-classes-and-exhaustive-pattern-matching/ آدرس نظرات: https://news.ycombinator.com/item?id=50141579 امتیاز: 181 # نظرات: 144
جاوا 17 کلاسهای مهر و موم شده را معرفی کرد که به شما امکان میدهد به صراحت زیر انواع مجاز یک رابط یا کلاس پایه را فهرست کنید. به عنوان مثال، در اینجا یک مثال اسباب بازی با استفاده از یک رابط مهر و موم شده و رکوردها آورده شده است (کلاس های داخلی به طور ضمنی به زیرشاخه های مجاز اضافه می شوند اگر یک لیست صریح ارائه نشود):
اگر با زبانهای برنامهنویسی تابعی با انواع دادههای جبری آشنا هستید، میتوانید آن را شبیه به یک اعلان نوع داده در Haskell یا ML مشاهده کنید:
خوب، خیلی هیجان انگیز نیست. اما نکته ای که در اینجا باید به آن توجه کرد این است که ما مجبور نبودیم یک بند پیش فرض به عبارت switch در متد اصلی خود اضافه کنیم. این به این دلیل است که کلاسهای مهر و موم شده (و enums) بررسی جامع بودن را امکانپذیر میکنند: کامپایلر دقیقا میداند که موارد ممکن چیست، و بنابراین میتواند بررسی کند که آیا همه آنها را پوشش دادهاید یا خیر. اگر دارید، پس نیازی به بند پیش فرض ندارید. اگر یکی را فراموش کردید (و یک بند پیش فرض ندارید)، یک خطای زمان کامپایل دریافت می کنید.
این زمانی عالی است که میخواهید اطمینان حاصل کنید که همه استفادههای یک نوع همه موارد را پوشش میدهند، اما نوع جدیدی از تغییر شکست را معرفی میکند: افزودن یک نوع فرعی جدید به یک کلاس/رابط مهر و موم شده ممکن است مصرفکنندگان آن کد را خراب کند. به عنوان مثال، افزودن یک مورد TypeC جدید به مثال ما باعث میشود که متد اصلی به دلیل کمبود حروف کامپایل نشود. بنابراین، اگر یک نوع مهر و موم شده را در API خود صادر می کنید، اضافه کردن یک نوع فرعی جدید یک تغییر قطعی است که به یک نسخه اصلی نیاز دارد (اگر SemVer را دنبال می کنید).
اگرچه جاوا هنگام کامپایل کردن مصرف کننده (در این مورد اصلی) یک خطای زمان کامپایل برای یک سوئیچ غیر جامع ایجاد می کند، اگر زمانی که نوع مهر و موم شده تغییر می کند، مصرف کننده دوباره کامپایل نشود، نمی تواند این کار را انجام دهد. برای مثال، فرض کنید که SealedType خود را با یک مورد دیگر گسترش دهیم:
اگر فقط SealedType.java را مجددا کامپایل کرده باشیم و Main را مجددا کامپایل نکنیم، اگر مورد جدید را راه اندازی کنیم، با یک استثنا در زمان اجرا مواجه می شویم:
در اینجا ما MatchException جدید را داریم که پرتاب می شود. Javadoc این مشکل بالقوه را با کامپایل جداگانه، و همچنین برخی از گوشهها با تهی الگوها یادداشت میکند. بنابراین حتی اگر امیدوار بودید که استفاده از کلاسهای مهر و موم شده به طور ایستا اطمینان حاصل کند که وقتی یک کیس جدید اضافه میشود، همه مصرفکنندگان را بهروزرسانی میکنید، اینطور نیست مگر اینکه همه چیز را دوباره کامپایل کنید.
من فکر می کنم برای من نتیجه این است که انواع مهر و موم شده احتمالا در اجرای یک مؤلفه بسیار مفید هستند، و زمانی که در API عمومی که یک مؤلفه به مؤلفه های دیگر ارائه می دهد (مثلا یک کتابخانه) قرار می گیرند، کمتر مفید هستند. برای استفاده داخلی، جایی که معمولا میخواهید همه چیز را دوباره کامپایل کنید، ویژگیهای خوب بررسی جامع بودن و تضمینهای ایمنی بالاتر در زمان کامپایل را دریافت میکنید. اما هنگامی که در سراسر مرزهای ماژول استفاده می شود، ممکن است فقط راه های جدیدی را برای شکستن کد معرفی کنید، که اغلب فقط در زمان اجرا قابل تشخیص هستند.
(این ظرافتها را هنگام بررسی پشتیبانی پیشنمایش برای اشیاء رمزنگاریشده با رمزگذاری PEM کشف کردم، که دقیقا این اشتباه را مرتکب میشود که یک رابط مهر و موم شده را در یک API عمومی آماده میکند و به مشتریان توصیه میکند الگوی مشابهی با آن نوع داشته باشند. پیشبینی میکند که اگر زمانی بخواهند مورد جدیدی اضافه کنند، احتمال شکستگی بسیار بالایی دارد).
متن اصلی (انگلیسی)
Java sealed classes and exhaustive pattern matching
Article URL: https://neilmadden.blog/2026/04/24/java-sealed-classes-and-exhaustive-pattern-matching/ Comments URL: https://news.ycombinator.com/item?id=50141579 Points: 181 # Comments: 144