Faragiri

همهٔ زبان‌ها

آموزش شی و کتابخانه در جاوا جاوا

رکورد، اینترفیس، کلاس انتزاعی و کلاس نهایی. دو پرسش درباره داده و درباره وراثت، هر بار یکی از این چهار را انتخاب می‌کنند.

۴بخش
۳دقیقه خواندن
۴عمق

دو پرسش، چهار شکل

کدام اعلان، بر اساس داده بودن و ارث‌بری

دو محور این شبکه دو تصمیم جدا هستند و هر ترکیبشان یک کلمه کلیدی متفاوت در جاوا دارد.

فقط داده استرفتار دارد

قرار است ارث برده شود

اینترفیستوانایی را نام می‌برد و می‌تواند متد پیش‌فرض داشته باشد
  • interface Gheymatdar { long rialBarVahed(); }
کلاس انتزاعیرفتار مشترک به‌همراه فیلد مشترک، و خودش کامل نیست
  • abstract class Bar

قرار نیست ارث برده شود

رکوردداده تغییرناپذیر، و خودش نهایی است
  • record Qet(String kod, int mojoodi) {}
کلاس نهاییرفتار دارد و کسی نباید از آن ارث ببرد
  • final class Faktor

این شبکه انتخاب اول را می‌گوید و نه انتخاب آخر. کلاس مهروموم‌شده جای پنجمی است که میان دو خانه بالا می‌نشیند: ارث‌بری مجاز است، اما فقط برای فهرستی که خودتان نوشته‌اید.

در جاوا هر بار که چیزی تازه می‌سازید، چهار شکل پیش رو دارید و انتخاب میانشان با دو پرسش انجام می‌شود: آیا این چیز فقط داده است، و آیا قرار است کسی از آن ارث ببرد.

  • record Qet(String kod, int mojoodi) {} برای داده‌ای که پس از ساخت عوض نمی‌شود
  • interface Gheymatdar { long rialBarVahed(); } برای نام بردن یک توانایی
  • abstract class Bar برای رفتار مشترکی که خودش کامل نیست
  • final class Faktor برای چیزی که رفتار دارد و نباید از آن ارث برد

رکورد خودش نهایی است و فیلدهایش تغییرناپذیرند، پس دو تصمیم را با خودش می‌آورد. اگر لازم شد داده‌ای پس از ساخت عوض شود، رکورد شکل درستی نیست و باید کلاس بنویسید؛ این محدودیت نیست، همان قراردادی است که رکورد برایش ساخته شده.

اینترفیس امروز فقط یک فهرست امضا نیست

از Java 8 به بعد اینترفیس می‌تواند متد پیش‌فرض داشته باشد، یعنی پیاده‌سازی که همه پیاده‌کننده‌ها به ارث می‌برند مگر آنکه بازنویسی کنند. این همان چیزی است که اضافه کردن متد تازه به یک اینترفیس منتشرشده را ممکن می‌کند بی‌آنکه هر کدی که آن را پیاده کرده بشکند.

پس مرز میان اینترفیس و کلاس انتزاعی امروز باریک‌تر است و یک تفاوت واقعی باقی مانده: یک کلاس می‌تواند چند اینترفیس را پیاده کند و فقط از یک کلاس ارث ببرد. برای همین اینترفیس پیش‌فرض درست است و کلاس انتزاعی وقتی لازم می‌شود که حالت مشترک، یعنی فیلد، هم داشته باشید. همان انتخاب در پایتون شکل دیگری دارد: نام بردن یک توانایی، بدون نام بردن پیاده‌سازی.

پکیج مرز است، و کلمه‌ای که ندارید

جاوا چهار سطح دسترسی دارد و سطح پیش‌فرض، که هیچ کلمه‌ای برایش نمی‌نویسید، یعنی «فقط در همین پکیج». این سطح بیشتر از آنچه فکر می‌کنید به کار می‌آید: کلاسی که فقط پیاده‌سازی داخلی یک پکیج است نباید عمومی باشد، و همین یک تصمیم است که مرز واقعی یک ماژول را می‌سازد.

از Java 9 به بعد لایه دیگری هم هست که پکیج‌ها را در ماژول جمع می‌کند و می‌گوید کدام پکیج بیرون از ماژول قابل دیدن است. برای یک کتابخانه که دیگران استفاده می‌کنند این ارزش دارد و برای یک برنامه معمولی معمولا نه.

جایی که کار گیر می‌کند، ارث‌بری به‌عنوان راه اشتراک است

در آموزش‌های فارسی، شی‌گرایی تقریبا همیشه با وراثت معرفی می‌شود و ترکیب یا اصلا گفته نمی‌شود یا در آخر یک فصل. نتیجه‌اش کدی است که برای هر تفاوت کوچک یک کلاس فرزند می‌سازد و پس از یک سال درخت کلاس‌ها پنج سطح عمق دارد. علامتی که می‌گوید انتخاب اشتباه بوده ساده است: اگر کلاس فرزند بیشتر متدهای والد را بازنویسی می‌کند یا برایشان استثنا پرتاب می‌کند، رابطه «هست» نبوده و باید یک شی نگه می‌داشتید به‌جای اینکه از آن ارث ببرید. تفصیلش در به اشتراک گذاشتن رفتار، و جایی که تله می‌شود است.

ابزار، و سالی که این حرف درست است

در سال ۲۰۲۶، رکورد و کلاس مهروموم‌شده هر دو در Java 25 در دسترس‌اند و رایگان؛ کلاس مهروموم‌شده می‌گوید دقیقا کدام کلاس‌ها اجازه دارند از آن ارث ببرند، و با تطبیق الگو در switch ترکیب می‌شود تا کامپایلر بتواند بگوید حالتی جا مانده. این جفت، جای زنجیره instanceof و تبدیل دستی نوع را در جاوا گرفته که سال‌ها تنها راه بود.

پرسش بعدی این است که وقتی چند نمونه از این نوع‌ها را باید کنار هم نگه دارید، کدام ظرف درست است، که لیست، مپ و ست، و انتخاب میان آن‌ها است. و اصلی که همین چهار انتخاب را با نام می‌گوید در پنج اصل، و اینکه هرکدام جلوی چه چیزی را می‌گیرد است.

کنار این

بالای این