أساسيات البرمجة الكائنيّة

الحزم والاستيرادات

15 دقيقة الدرس 8 من 14

الحزم والاستيرادات

مع نمو برنامجك في Java وتجاوزه عدة كلاسات، تحتاج إلى طريقة لتنظيمها — تمامًا كما تنظّم الملفات في مجلدات على حاسوبك. تحل Java هذه المشكلة بـ الحزم (Packages). الحزمة هي مجموعة مسمّاة من الكلاسات والواجهات المترابطة. تخدم الحزم غرضين: تنظيم الكود، ومنع تعارض الأسماء بين كلاسات تشترك في الاسم ذاته.

تعليمة package

يمكن لكل ملف مصدري في Java أن يبدأ بتعليمة package تُعلن الحزمة التي ينتمي إليها الكلاس. يجب أن تكون هذه التعليمة أول سطر غير تعليقي في الملف.

package com.mybank.accounts; public class BankAccount { // ... }

تتبع أسماء الحزم نمط اسم النطاق معكوسًا باتفاقية. إذا كان نطاقك mybank.com، فالحزمة العليا هي com.mybank. تُقسَّم الحزم الفرعية الاهتمامات أكثر: com.mybank.accounts وcom.mybank.loans وcom.mybank.util.

أسماء الحزم تتوافق مع المجلدات. الكلاس المُعلَن بـ package com.mybank.accounts يجب أن يقع داخل المسار com/mybank/accounts/ نسبةً إلى جذر الكود المصدري. تُطبّق أدوات البناء الحديثة (Maven وGradle) وبيئات التطوير هذا القيد تلقائيًا.

الحزمة الافتراضية

إذا حذفت تعليمة package، انتمى الكلاس إلى الحزمة الافتراضية — حزمة بلا اسم. هذا مقبول في التجارب الصغيرة ذات الملف الواحد، لكن لا تستخدمه في مشاريع حقيقية لأن كلاسات الحزمة الافتراضية لا يمكن استيرادها من كلاسات ذات حزم مسمّاة.

استيراد الكلاسات بـ import

حين تريد استخدام كلاس من حزمة مختلفة، لديك خياران. الأول هو الاستيراد الفردي: تذكر الكلاس المحدد الذي تحتاجه.

package com.mybank.reports; import com.mybank.accounts.BankAccount; // استيراد فردي public class MonthlyReport { public void generate(BankAccount account) { System.out.println("Report for: " + account.getOwner()); } }

الخيار الثاني هو الاستيراد بالبدل الذي يجلب كل الأنواع العامة من حزمة:

import com.mybank.accounts.*; // يستورد كل الكلاسات العامة من تلك الحزمة
فضّل الاستيراد الفردي. الاستيراد بالبدل لا يُؤثر على الأداء (المُجمِّع يحلّه في وقت التجميع دون إضافة بايت كود إضافي)، لكنه يُصعّب معرفة مصدر الكلاس بنظرة واحدة. تُوسّع معظم منسّقات الكود وبيئات التطوير البدل تلقائيًا.

الأسماء المؤهَّلة بالكامل

يمكنك دائمًا الإشارة إلى كلاس بـ اسمه المؤهَّل بالكامل — المسار الكامل package.ClassName — دون أي تعليمة استيراد:

public class App { public static void main(String[] args) { com.mybank.accounts.BankAccount acc = new com.mybank.accounts.BankAccount("Alice", 0.0); System.out.println(acc.getOwner()); } }

الأسماء المؤهَّلة مطوّلة، لذا تُستخدم أساسًا حين تحتوي حزمتان على كلاسات بالاسم ذاته وتحتاج لكليهما في الملف نفسه:

import com.mybank.util.Date; // كلاس Date المخصص public class Transaction { private com.mybank.util.Date txDate; // كلاسك المخصص private java.util.Date legacyDate; // كلاس JDK — الاسم البسيط ذاته، حزمة مختلفة }

حزمة java.lang مستوردة دائمًا

استخدمت String وSystem وMath وInteger طوال الوقت دون استيرادها. السبب أن كل ملف Java يستورد تلقائيًا جميع كلاسات java.lang. لن تحتاج أبدًا لكتابة import java.lang.String.

الاستيرادات الساكنة

يتيح لك الاستيراد الساكن استخدام الأعضاء الساكنة (الحقول والوظائف) لكلاس آخر دون تأهيلها باسم الكلاس. الاستخدام الأكثر شيوعًا هو ثوابت ووظائف Math:

import static java.lang.Math.PI; import static java.lang.Math.sqrt; public class Circle { public double area(double radius) { return PI * radius * radius; // لا حاجة لبادئة Math. } public double hypotenuse(double a, double b) { return sqrt(a * a + b * b); } }
لا تُفرط في الاستيرادات الساكنة. إذا استوردت ساكنًا أعضاءً كثيرين من كلاسات متعددة، يصبح الكود صعب القراءة — لن يعرف القارئ من أي كلاس جاء sqrt أو PI. خصّص الاستيرادات الساكنة للثوابت ووظائف الأدوات المعروفة جيدًا (كـ Math أو تأكيدات JUnit).

هيكل حزم واقعي

إليك كيف يمكن تنظيم تطبيق مصرفي صغير في حزم:

src/ com/mybank/ accounts/ BankAccount.java // package com.mybank.accounts SavingsAccount.java loans/ Loan.java // package com.mybank.loans util/ CurrencyFormatter.java // package com.mybank.util App.java // package com.mybank

لكل حزمة مسؤولية واضحة. accounts تحتوي كلاسات الحسابات، وloans تحتوي كلاسات القروض، وutil تحتوي المساعدات المشتركة. هذا يعكس ما تعلّمته في الفصل بين الحقول والوظائف والمُنشئات داخل الكلاس — الآن تفعل الشيء ذاته على مستوى أعلى.

محدّدات الوصول والحزم مراجعة

تعلّمت عن public وprivate وprotected في الدرس الرابع. ثمة مستوى رابع ربما لم تنتبه إليه: package-private (بلا كلمة مفتاحية). الكلاس أو العضو الذي لا يحمل محدّد وصول يكون مرئيًا داخل حزمته فقط. هذا مفيد للمساعدات الداخلية التي تريد مشاركتها داخل الحزمة مع إخفائها عن بقية التطبيق.

package com.mybank.accounts; class AccountValidator { // لا محدّد = package-private static boolean isValidIban(String iban) { return iban != null && iban.length() == 22; } }

AccountValidator مرئي لكل كلاس داخل com.mybank.accounts لكنه غير مرئي لكلاسات الحزم الأخرى — طريقة نظيفة لإخفاء التفاصيل الداخلية.

الخلاصة

الحزم هي آلية Java لتنظيم الكلاسات والتحكم في رؤيتها. صرّح بحزمتك بتعليمة package في أعلى كل ملف مصدري، واستخدم import لجلب كلاسات من حزم أخرى، واعتمد الأسماء المؤهَّلة بالكامل حين تشترك حزمتان في اسم كلاس. حزمة java.lang متاحة دائمًا دون استيراد، والاستيرادات الساكنة تتيح استخدام الأعضاء الساكنة دون تأهيل — استخدمها باعتدال. تُتيح لك هذه الأدوات مجتمعةً بناء تطبيقات كبيرة تظل مقروءة وقابلة للصيانة.