الوحدة 4: المتغيرات، إسناد القيم، والدوال الأساسية

افهم كيف تخزن البيانات، تتعامل معها، وتنظم برامجك

المدة: أسبوعان 6 ساعات نظرية 6 ساعات عملية

المقدمة والأهداف التعليمية

تعد هذه الوحدة حجر الأساس في تعلم البرمجة بلغة جافا، حيث تتعلم فيها كيفية التعامل مع **المتغيرات** كأماكن لتخزين البيانات في الذاكرة، وأنواع البيانات المختلفة وخصائصها، وطرق **إسناد القيم** والتعامل مع الأخطاء الشائعة. بالإضافة إلى ذلك، ستتعرف على **الدوال (Methods)** كأداة أساسية لتنظيم الكود وإعادة استخدامه، وكيفية التفاعل مع المستخدم عبر **نوافذ `JOptionPane`** التفاعلية.

الأهداف:

بنهاية هذه الوحدة، ستكون قادرًا على:

  • تعريف المتغيرات بأنواعها المختلفة (بدائية وغير بدائية).
  • إسناد القيم للمتغيرات بطرق متعددة وتنفيذ العمليات الحسابية والمنطقية عليها.
  • فهم مفهوم الدوال وأهميتها في تنظيم الكود وإعادة استخدامه.
  • استخدام نوافذ `JOptionPane` لعرض الرسائل وأخذ المدخلات من المستخدم.
  • تجنب الأخطاء الشائعة في التعامل مع المتغيرات والدوال.
---

الجزء الأول: المتغيرات وإسناد القيم

1. مفهوم المتغيرات في جافا

تخيلوا أن الحاسوب مثل مكتبة ضخمة. هذه المكتبة مليئة بالرفوف. نحن كمبرمجين نريد أن نخزن معلوماتنا على هذه الرفوف، مثل اسم شخص، عمره، أو حتى نتيجة عملية حسابية. هذا "الرف" الذي نتحدث عنه هو **المتغير (Variable)**.

المتغير هو بمثابة صندوق تخزين في ذاكرة الحاسوب نضع بداخلها البيانات التي نريد التعامل معها أثناء تشغيل البرنامج. لكل متغير ثلاثة عناصر أساسية:

  • اسم (Identifier): وهو المعرف الذي نستخدمه للدلالة عليه، مثل age أو userName.
  • نوع بيانات (Data Type): يحدد طبيعة البيانات التي يمكن تخزينها (مثل أعداد صحيحة int، أو نصوص String).
  • قيمة (Value): وهي المحتوى المخزن بداخل المتغير ويمكن تغييره أثناء التنفيذ.

مثال بسيط لتعريف المتغيرات:

int age = 25;                // متغير يخزن عدد صحيح يمثل العمر
String name = "أحمد";        // متغير يخزن نص يمثل الاسم
boolean isStudent = true;    // متغير يخزن قيمة منطقية (صحيح/خطأ)
لنفكر معًا:

إذا أردت أن أخزن "درجة حرارة الجو" كعدد عشري مثل 32.5، هل أستخدم int أم double؟

الجواب: يجب أن تستخدم double. السبب هو أن int يستخدم فقط للأعداد الصحيحة (بدون كسور)، بينما double مناسب لتخزين الأعداد العشرية بدقة عالية.

2. أنواع المتغيرات الرئيسية في جافا

تنقسم المتغيرات في جافا إلى نوعين رئيسيين:

أ. الأنواع البدائية (Primitive Types)

هذه الأنواع تخزن القيم مباشرة وهي بسيطة وسريعة. لكل نوع منها حجم محدد في الذاكرة ودقة معينة. إليك الأنواع البدائية الشائعة:

  • الأعداد الصحيحة:
    • byte (1 بايت): للأعداد الصغيرة جداً من -128 إلى 127. القيمة الافتراضية: `0`.
    • short (2 بايت): للأعداد الصحيحة المتوسطة من -32,768 إلى 32,767. القيمة الافتراضية: `0`.
    • int (4 بايت): النوع الأكثر شيوعًا للأعداد الصحيحة، من حوالي $-2 \times 10^9$ إلى $2 \times 10^9$. القيمة الافتراضية: `0`.
    • long (8 بايت): للأعداد الصحيحة الكبيرة جداً. القيمة الافتراضية: `0L`. ملاحظة: يجب إضافة الحرف L أو l (يفضل الكبير لتجنب الالتباس مع الرقم واحد) في نهاية القيمة لتحديد أنها من نوع long.
  • الأعداد العشرية (الفاصلة العائمة):
    • float (4 بايت): للأعداد العشرية بدقة واحدة. القيمة الافتراضية: `0.0f`. ملاحظة: يجب إضافة الحرف f أو F في نهاية القيمة.
    • double (8 بايت): النوع الأكثر شيوعًا للأعداد العشرية بدقة مضاعفة، وهو الافتراضي للقيم العشرية. القيمة الافتراضية: `0.0d` (الحرف `d` اختياري).
  • الحروف:
    • char (2 بايت): لتخزين حرف واحد، ويستخدم ترميز يونيكود (Unicode). يوضع الحرف بين علامتي اقتباس مفردتين ' '. القيمة الافتراضية: `\u0000` (حرف فارغ).
  • القيم المنطقية:
    • boolean (1 بت): لتخزين قيمتين فقط: true (صحيح) أو false (خطأ). القيمة الافتراضية: `false`.

ب. الأنواع غير البدائية (Non-Primitive Types)

هذه الأنواع أكثر تعقيدًا ولا تخزن القيمة مباشرة، بل تخزن "عنوانًا" لمكان القيمة في الذاكرة. يتم إنشاؤها باستخدام الكلاسات (Classes) وتتضمن:

  • String (سلسلة نصية): يستخدم لتخزين النصوص المتعددة الأحرف. ملاحظة هامة: String ليس نوعًا بدائيًا وإنما كلاس في جافا، وهو جزء من مكتبة جافا القياسية. قيمته الافتراضية: `null`.
    String message = "مرحبًا بكم في عالم جافا!";
    
  • المصفوفات (Arrays): تستخدم لتخزين مجموعة من القيم من نفس النوع.
    int[] numbers = {1, 2, 3, 4, 5};
    
  • الكائنات (Objects): أي كائن يتم إنشاؤه من كلاس.
    // مثال: كائن من كلاس Scanner لقراءة المدخلات
    Scanner input = new Scanner(System.in); 
    

3. طرق إسناد القيم للمتغيرات

يمكن إسناد القيم للمتغيرات بعدة طرق رئيسية:

أ. التعريف بدون قيمة (Declaration) ثم الإسناد لاحقًا (Assignment)

في هذه الطريقة، تقوم أولاً بتعريف المتغير (حجز مساحة له)، ثم في سطر لاحق تقوم بإسناد قيمة له.

int x;  // هنا تم تعريف المتغير x فقط، ولم تُسند له قيمة بعد
x = 10;  // هنا تم إسناد القيمة 10 للمتغير x

ب. التعريف مع الإسناد (Initialization)

هذه هي الطريقة الأكثر شيوعًا، حيث تقوم بتعريف المتغير وإسناد قيمة أولية له في نفس السطر.

int y = 20;  // تعريف المتغير y وإسناد القيمة 20 له في نفس السطر
String name = "محمد"; // تعريف متغير نصي وإسناد قيمة له

ج. تعريف متغيرات متعددة في سطر واحد

يمكنك تعريف عدة متغيرات من نفس النوع في سطر واحد لتوفير المساحة وتنظيم الكود، مع إمكانية إسناد قيم فورية لها أو لاحقًا.

int a = 5, b = 10, c = 15;  // تعريف وإسناد قيم لثلاث متغيرات صحيحة
String firstName = "Ali", lastName = "Mohamed";  // تعريف وإسناد قيم لمتغيرين نصيين

د. الإسناد الشرطي (Conditional Assignment / Ternary Operator)

تعبير شرطي مختصر يستخدم لإسناد قيمة بناءً على صحة شرط معين. صيغته تكون كالتالي: المتغير = (الشرط) ? القيمة_إذا_صحيح : القيمة_إذا_خطأ;

int grade = 75;
int score = (grade >= 60) ? 100 : 50; // إذا كانت grade أكبر أو تساوي 60، فـ score = 100، وإلا فـ score = 50.
System.out.println("الدرجة: " + score); // الناتج: 100

هـ. الإسناد المركب (Compound Assignment Operators)

تستخدم لتبسيط العمليات الحسابية التي تتضمن المتغير نفسه. على سبيل المثال، بدلاً من كتابة a = a + 3;، يمكنك استخدام a += 3;.

  • += (جمع وإسناد): a += 3; تعادل a = a + 3;
  • -= (طرح وإسناد): a -= 3; تعادل a = a - 3;
  • *= (ضرب وإسناد): a *= 3; تعادل a = a * 3;
  • /= (قسمة وإسناد): a /= 3; تعادل a = a / 3;
  • %= (باقي قسمة وإسناد): a %= 3; تعادل a = a % 3;
int a = 5;
a += 3;   // الآن قيمة a أصبحت 8 (5 + 3)
System.out.println("القيمة الجديدة لـ a: " + a); // الناتج: 8

4. العمليات الحسابية والمنطقية على المتغيرات

أ. العمليات الحسابية (Arithmetic Operations)

هذه العمليات هي نفسها العمليات الرياضية الأساسية وتستخدم لإجراء الحسابات على القيم العددية:

  • **الجمع (`+`):** يجمع قيمتين.
  • **الطرح (`-`):** يطرح قيمة من أخرى.
  • **الضرب (`*`):** يضرب قيمتين.
  • **القسمة (`/`):** يقسم قيمة على أخرى. ملاحظة: إذا كان كلا المعاملين عددين صحيحين، فإن الناتج سيكون عددًا صحيحًا (سيتم تجاهل الجزء العشري). للحصول على نتيجة عشرية، يجب أن يكون أحد المعاملين على الأقل من نوع عشري (مثل `double`).
  • **الباقي (`%`):** يعيد باقي القسمة لعدد صحيح على آخر.

مثال شامل على العمليات الحسابية:

int a = 20, b = 3;
System.out.println("الجمع: " + (a + b));      // الناتج: 23
System.out.println("الطرح: " + (a - b));      // الناتج: 17
System.out.println("الضرب: " + (a * b));      // الناتج: 60
System.out.println("القسمة (صحيح): " + (a / b));  // الناتج: 6 (لأنها قسمة أعداد صحيحة)

double d_a = 20.0, d_b = 3.0;
System.out.println("القسمة (عشري): " + (d_a / d_b)); // الناتج: 6.666666666666667

System.out.println("الباقي: " + (a % b));    // الناتج: 2 (باقي قسمة 20 على 3)

ب. العمليات المنطقية (Logical Operations)

تستخدم هذه العمليات للجمع بين الشروط أو مقارنة القيم المنطقية (`boolean`)، وتكون نتيجتها دائمًا `true` أو `false`:

  • **و (`&&` - AND):** تعني "وكلا الشرطين يجب أن يكونا صحيحين". تكون النتيجة `true` فقط إذا كان كلا الشرطين صحيحين.
  • **أو (`||` - OR):** تعني "يكفي أن يكون أحد الشرطين صحيحًا". تكون النتيجة `true` إذا كان أي من الشرطين (أو كلاهما) صحيحًا.
  • **ليس (`!` - NOT):** تعني "عكس القيمة". تعكس القيمة المنطقية (تحول `true` إلى `false` والعكس).
boolean isAdult = true;
boolean hasLicense = false;

System.out.println("هل هو بالغ ولديه رخصة؟ " + (isAdult && hasLicense)); // الناتج: false
System.out.println("هل هو بالغ أو لديه رخصة؟ " + (isAdult || hasLicense)); // الناتج: true
System.out.println("هل هو ليس ببالغ؟ " + (!isAdult)); // الناتج: false
---

الجزء الثاني: مقدمة في الدوال (Methods)

1. مفهوم الدوال في جافا

تخيل أنك تكتب برنامجًا كبيرًا، وتحتاج إلى تنفيذ نفس مجموعة التعليمات عدة مرات في أماكن مختلفة. هل ستكرر كتابة نفس الكود في كل مرة؟ بالتأكيد لا! هنا تأتي فائدة **الدوال (Methods)**.

**الدالة** هي كتلة من التعليمات البرمجية يتم وضعها داخل البرنامج بهدف تنفيذ مهمة معينة عند استدعائها. يمكن اعتبار الدالة كـ "وصفة" أو "مهمة" محددة، حيث تحتوي على الخطوات اللازمة لإنجاز عمل ما.

فوائد استخدام الدوال:

  • تقليل التكرار وإعادة استخدام الكود (Reusability): تكتب الكود مرة واحدة وتستدعيه عدة مرات.
  • جعل البرنامج أكثر تنظيمًا (Modularity): يقسم البرنامج إلى أجزاء صغيرة يمكن التحكم بها بسهولة.
  • تسهيل التعديل والصيانة (Maintainability): إذا أردت تغيير جزء من المنطق، تعدله في مكان واحد فقط داخل الدالة.

2. أمثلة على دوال جاهزة في جافا

تحتوي جافا على العديد من الدوال الجاهزة التي يمكنك استخدامها مباشرة:

  • دالة الطباعة (`System.out.println()`): هذه دالة جاهزة تستخدم لطباعة النصوص على شاشة الكونسول.
    System.out.println("Hello World!"); // تستدعي دالة println لطباعة النص
    
  • دوال من مكتبة `Math`: هذه المكتبة توفر دوال رياضية جاهزة.
    int maxVal = Math.max(5, 10);  // دالة Math.max() ترجع العدد الأكبر بين قيمتين (هنا 10)
    System.out.println("القيمة الأكبر: " + maxVal); // الناتج: 10
    

3. كيفية كتابة دالة خاصة بك

لكتابة دالتك الخاصة في جافا، تحتاج إلى تحديد بعض العناصر الأساسية:

بنية الدالة العامة:

[وصف الوصول] [نوع الإرجاع] اسم_الدالة([المعاملات]) {
    // جسم الدالة: هنا تكتب التعليمات البرمجية التي تنفذها الدالة
    return [قيمة];   // إذا كان نوع الإرجاع غير 'void'، يجب أن ترجع الدالة قيمة من هذا النوع
}
  • `[وصف الوصول]` (Access Modifier): يحدد من يمكنه الوصول إلى هذه الدالة (مثل `public`, `private`, `protected`). `public` يعني أنها متاحة من أي مكان.
  • `[static]` (اختياري): كلمة مفتاحية تعني أن الدالة تنتمي إلى الكلاس نفسه، وليس إلى كائن معين منه. تستخدم غالبًا مع الدوال التي لا تحتاج إلى كائن لتشغيلها، مثل الدالة `main`.
  • `[نوع الإرجاع]` (Return Type): يحدد نوع القيمة التي سترجعها الدالة بعد انتهاء تنفيذها. إذا لم ترجع الدالة أي قيمة، نستخدم الكلمة المفتاحية `void`.
  • `اسم_الدالة` (Method Name): اسم فريد للدالة.
  • `[المعاملات]` (Parameters): قائمة بالمتغيرات التي تستقبلها الدالة كمدخلات (اختياري). تُفصل المعاملات بفاصلة `,` وتُكتب بين قوسين `()`.
  • `جسم الدالة` (Method Body): الكود الفعلي الذي تنفذه الدالة، محاطًا بالأقواس المعقوفة `{}`.
  • `return` (اختياري): تستخدم لإرجاع قيمة من الدالة إذا كان `نوع الإرجاع` ليس `void`.

مثال على دالة تقوم بجمع عددين:

public class MyMathOperations {

    /**
     * هذه الدالة تقوم بجمع عددين صحيحين وإرجاع الناتج.
     * @param a العدد الصحيح الأول.
     * @param b العدد الصحيح الثاني.
     * @return مجموع العددين a و b.
     */
    public static int sum(int a, int b) {
        int result = a + b; // نحسب المجموع
        return result;      // نرجع قيمة المجموع
    }

    public static void main(String[] args) {
        // استدعاء الدالة sum()
        int finalResult = sum(5, 3);  // هنا نستدعي الدالة ونمرر لها 5 و 3
        System.out.println("المجموع هو: " + finalResult); // الناتج: 8

        int anotherSum = sum(10, 20); // يمكننا استدعاء الدالة مرة أخرى بقيم مختلفة
        System.out.println("مجموع آخر: " + anotherSum); // الناتج: 30
    }
}
---

الجزء الثالث: الطباعة والإدخال باستخدام JOptionPane

حتى الآن، استخدمنا System.out.println() للطباعة على "الشاشة السوداء" (الكونسول). ولكن في جافا، يمكننا إنشاء نوافذ تفاعلية صغيرة (Pop-up windows) للتفاعل مع المستخدم بشكل رسومي، وهذا يتم من خلال مكتبة **`javax.swing.JOptionPane`**.

تذكر:

لكي تتمكن من استخدام `JOptionPane`، يجب عليك استيرادها في بداية ملف الجافا الخاص بك باستخدام الأمر: import javax.swing.JOptionPane;

1. عرض رسالة للمستخدم (`showMessageDialog`)

تستخدم هذه الدالة لعرض رسالة بسيطة للمستخدم في نافذة منبثقة.

import javax.swing.JOptionPane; // يجب استيراد المكتبة

public class MessageDialogExample {
    public static void main(String[] args) {
        // null: يعني أن النافذة ستظهر في منتصف الشاشة
        // "مرحبًا بك!": الرسالة التي ستظهر للمستخدم
        // "رسالة ترحيب": عنوان النافذة
        // JOptionPane.INFORMATION_MESSAGE: نوع الأيقونة التي ستظهر (هنا أيقونة معلومات)
        JOptionPane.showMessageDialog(null, "مرحبًا بك!", "رسالة ترحيب", JOptionPane.INFORMATION_MESSAGE);
    }
}

2. إدخال بيانات من المستخدم (`showInputDialog`)

تستخدم هذه الدالة لعرض نافذة تطلب من المستخدم إدخال نص، ثم تُرجع النص الذي أدخله المستخدم كـ `String`.

import javax.swing.JOptionPane;

public class InputDialogExample {
    public static void main(String[] args) {
        // تعرض نافذة تطلب من المستخدم إدخال اسمه
        String name = JOptionPane.showInputDialog("أدخل اسمك:");
        
        // تعرض الرسالة التي أدخلها المستخدم
        JOptionPane.showMessageDialog(null, "أهلاً بك، " + name + "!", "الترحيب", JOptionPane.PLAIN_MESSAGE);
    }
}

3. تحويل النصوص المدخلة إلى أعداد (Data Conversion)

دائمًا ما تُرجع دالة `showInputDialog()` قيمة من نوع `String` (نص). إذا أردت التعامل مع هذه المدخلات كأرقام (مثلاً لإجراء عمليات حسابية)، يجب عليك تحويلها من `String` إلى النوع الرقمي المطلوب (مثل `int` أو `double`).

  • **لتحويل `String` إلى `int`:** نستخدم Integer.parseInt().
  • **لتحويل `String` إلى `double`:** نستخدم Double.parseDouble().
import javax.swing.JOptionPane;

public class DataConversionExample {
    public static void main(String[] args) {
        String input = JOptionPane.showInputDialog("أدخل عمرك:");
        // تحويل النص (String) المدخل إلى عدد صحيح (int)
        int age = Integer.parseInt(input);
        
        JOptionPane.showMessageDialog(null, "عمرك هو: " + age + " سنة.", "العمر", JOptionPane.INFORMATION_MESSAGE);

        String priceInput = JOptionPane.showInputDialog("أدخل سعر المنتج:");
        // تحويل النص (String) المدخل إلى عدد عشري (double)
        double price = Double.parseDouble(priceInput);
        
        JOptionPane.showMessageDialog(null, "سعر المنتج: " + price + " ريال.", "السعر", JOptionPane.INFORMATION_MESSAGE);
    }
}

4. مثال تطبيقي – حاسبة بسيطة باستخدام `JOptionPane`

import javax.swing.JOptionPane; // استيراد مكتبة JOptionPane

public class Calculator {
    public static void main(String[] args) {
        // طلب الرقم الأول من المستخدم كنص
        String num1Str = JOptionPane.showInputDialog("أدخل الرقم الأول:");
        // طلب الرقم الثاني من المستخدم كنص
        String num2Str = JOptionPane.showInputDialog("أدخل الرقم الثاني:");

        // تحويل النصوص المدخلة إلى أعداد عشرية (double) لإجراء العمليات الحسابية
        double a = Double.parseDouble(num1Str);
        double b = Double.parseDouble(num2Str);

        // إجراء عملية الجمع
        double sum = a + b;

        // عرض النتيجة للمستخدم في نافذة رسالة
        // JOptionPane.PLAIN_MESSAGE: لعدم عرض أي أيقونة (رسالة نصية عادية)
        JOptionPane.showMessageDialog(null, "المجموع: " + sum, "النتيجة", JOptionPane.PLAIN_MESSAGE);
    }
}
---

الخلاصة

لقد قمنا في هذه الوحدة بتغطية مفاهيم أساسية وحيوية في برمجة جافا:

  • **المتغيرات:** هي صناديق تخزن البيانات المؤقتة داخل ذاكرة الحاسوب، وتعرفنا على أنواعها البدائية وغير البدائية (مثل `String`).
  • **إسناد القيم:** تعلمنا طرقًا مختلفة لإسناد القيم للمتغيرات، سواء بشكل مباشر، أو باستخدام التعبيرات الشرطية، أو عوامل الإسناد المركبة.
  • **العمليات:** استعرضنا العمليات الحسابية الأساسية والعمليات المنطقية التي تمكننا من معالجة البيانات واتخاذ القرارات في برامجنا.
  • **الدوال (Methods):** فهمنا أهمية الدوال في تنظيم الكود، تقليل التكرار، وتسهيل صيانة البرنامج من خلال تجميع الأوامر ذات الصلة.
  • **`JOptionPane`:** تعرفنا على كيفية استخدام هذه المكتبة لإنشاء واجهات رسومية بسيطة (نوافذ منبثقة) للتفاعل مع المستخدم، سواء بعرض الرسائل أو أخذ المدخلات، وكيفية تحويل النصوص المدخلة إلى أرقام.

بفهمك لهذه المفاهيم، أنت الآن تمتلك أدوات قوية لبناء برامج جافا أكثر تعقيدًا وتفاعلية.

---

تمارين مقترحة للطلاب

1. تمرين: دالة لتحويل درجة الحرارة

اكتب برنامج جافا يحتوي على دالة باسم `fahrenheitToCelsius` تستقبل درجة حرارة بالفهرنهايت (نوع `double`)، وتحولها إلى درجة مئوية باستخدام المعادلة: $C = (F - 32) \times \frac{5}{9}$، ثم تُرجع القيمة المئوية. في الدالة الرئيسية `main`، استدعي هذه الدالة بقيمة فهرنهايت ثابتة (مثلاً 68.0) واطبع الناتج على الكونسول.

public class TemperatureConverterExercise {
    // اكتب الدالة fahrenheitToCelsius هنا
    public static double fahrenheitToCelsius(double fahrenheit) {
        // قم بكتابة كود التحويل هنا
        return 0.0; // placeholder
    }

    public static void main(String[] args) {
        // استدعي الدالة واطبع الناتج
    }
}

2. تمرين: نافذة معلومات المستخدم

صمم برنامج جافا يستخدم `JOptionPane` لطلب اسم المستخدم وعمره في نوافذ إدخال منفصلة. بعد الحصول على البيانات، اعرضها في نافذة رسالة واحدة بتنسيق: "مرحبًا [الاسم]! عمرك [العمر] سنة."

import javax.swing.JOptionPane;

public class UserInfoDialog {
    public static void main(String[] args) {
        // اكتب الكود هنا لطلب الاسم والعمر وعرضهما
    }
}

3. تمرين: دالة لإيجاد العدد الأكبر

اكتب برنامج جافا يحتوي على دالة باسم `findLargest` تستقبل عددين صحيحين (`int`)، وتُرجع العدد الأكبر بينهما. في الدالة الرئيسية `main`، اطلب من المستخدم إدخال عددين عبر `JOptionPane`، ثم استخدم الدالة `findLargest` لإيجاد العدد الأكبر واعرض النتيجة في نافذة رسالة.

import javax.swing.JOptionPane;

public class LargestNumberFinder {
    // اكتب الدالة findLargest هنا
    public static int findLargest(int num1, int num2) {
        // قم بكتابة كود المقارنة هنا
        return 0; // placeholder
    }

    public static void main(String[] args) {
        // اكتب الكود هنا لطلب الأرقام واستدعاء الدالة وعرض النتيجة
    }
}
---

المراجع

  • موقع Oracle Java Documentation.
  • "Java: A Beginner's Guide" – Herbert Schildt.
  • "Head First Java" – Kathy Sierra, Bert Bates.