0Pricing
Java Academy · درس

تحويل الأنواع عمليًا

طبّق تحويل الأنواع في سيناريوهات واقعية، بما في ذلك الحسابات الرقمية وتسلسلات OOP الهرمية

تحويل الأنواع عمليًا درس مجاني في Java Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Java Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Java Academy 4 دروس في المجموع.

التحويل النوعي عمليًا

يُستخدم التحويل النوعي في كل مواضع شيفرة Java العملية تقريبًا: في الحسابات الرقمية، وتسلسلات البرمجة كائنية التوجه، والمجموعات العامة، وواجهات برمجة التطبيقات القديمة. يغطي هذا الدرس الأنماط العملية والأخطاء المحتملة.

التحويل التصاعدي: تعدد الأشكال

يحوّل التحويل التصاعدي نوعًا فرعيًا إلى نوع أب. وهو آمن دائمًا ويُجرى ضمنيًا، فلا حاجة إلى عامل تحويل نوعي. ويتيح ذلك تعدد الأشكال.

class Payment {}
class CreditCardPayment extends Payment {
    public void authorizeCard() {}
}

CreditCardPayment cc = new CreditCardPayment();
Payment p = cc; // implicit upcast — always safe

// p.authorizeCard(); // Compile error — Payment doesn't have this method
// need downcast to access subclass methods

التحويل التنازلي: الوصول إلى أعضاء النوع الفرعي

يحوّل التحويل التنازلي مرجعًا من نوع أب مجددًا إلى النوع الفرعي الأصلي. ويتطلب تحويلًا نوعيًا صريحًا، ويطرح ClassCastException إذا لم يكن الكائن من ذلك النوع الفرعي فعلًا.

Payment p = new CreditCardPayment();

// Downcast to access CreditCardPayment-specific method
if (p instanceof CreditCardPayment cc) {
    cc.authorizeCard(); // safe with pattern matching
    System.out.println("Card authorized");
}

// Unsafe downcast without check:
try {
    BankTransfer bt = (BankTransfer) p; // ClassCastException!
} catch (ClassCastException e) {
    System.out.println("Wrong type!");
}

التحويل النوعي للأعداد في الحسابات

يؤدي تقسيم الأعداد الصحيحة إلى القطع. أجرِ تحويلًا نوعيًا إلى double قبل القسمة للحصول على نتيجة دقيقة. وهذا أحد أكثر الأخطاء الحسابية شيوعًا في Java.

int totalRevenue = 1000;
int months = 3;

// Integer division — truncates!
double wrong = totalRevenue / months;
System.out.println(wrong); // 333.0 (not 333.33)

// Correct: cast one operand to double first
double correct = (double) totalRevenue / months;
System.out.println(correct); // 333.3333333333333

التحويل النوعي في المجموعات (قبل الأنواع العامة)

غالبًا ما تخزّن الشيفرة القديمة الكائنات في مجموعات خام. ويكون التحويل التنازلي ضروريًا لاسترداد القيم ذات النوع المحدد؛ لذا تحقّق دائمًا باستخدام instanceof أولًا.

import java.util.*;

// Legacy raw list (pre-Java 5 style)
List legacyList = new ArrayList();
legacyList.add("Alice");
legacyList.add(42);

for (Object item : legacyList) {
    if (item instanceof String s) {
        System.out.println("Name: " + s.toUpperCase());
    } else if (item instanceof Integer n) {
        System.out.println("Score: " + (n * 2));
    }
}

التحويل النوعي باستخدام الواجهات

يمكن تحويل الكائن نوعيًا إلى أي واجهة ينفذها، مما يتيح لك استخدامه في السياقات التي تتطلب تلك الواجهة.

interface Printable { void print(); }
interface Saveable  { void save(); }

class Report implements Printable, Saveable {
    public void print() { System.out.println("Printing report"); }
    public void save()  { System.out.println("Saving report"); }
}

Object obj = new Report();

if (obj instanceof Printable p) p.print();
if (obj instanceof Saveable s) s.save();

التحويل النوعي باستخدام المصفوفات

تشكّل أنواع المصفوفات تسلسلًا هرميًا خاصًا بها. ويُعد String[] نوعًا فرعيًا من Object[]. وتتبع التحويلات النوعية للمصفوفات القواعد نفسها المتبعة مع الكائنات.

String[] names = {"Alice", "Bob"};
Object[] objs = names;   // upcast — implicit

objs[0] = "Charlie";     // OK — still a String

try {
    objs[0] = 42;          // ArrayStoreException at runtime!
} catch (ArrayStoreException e) {
    System.out.println("Cannot store Integer in String[]");
}

// Downcast back
String[] restored = (String[]) objs;

مثال للتجارة الإلكترونية: توجيه عمليات الدفع

مثال عملي: توجيه العملية إلى معالج الدفع الصحيح استنادًا إلى نوع الدفع وقت التشغيل.

interface Payment { double amount(); }
record CreditCard(String last4, double amount) implements Payment {}
record CryptoPayment(String wallet, double amount) implements Payment {}
record BankWire(String iban, double amount) implements Payment {}

static void process(Payment p) {
    switch (p) {
        case CreditCard cc     -> System.out.println("Charging card *" + cc.last4());
        case CryptoPayment cp  -> System.out.println("Sending to wallet " + cp.wallet());
        case BankWire bw       -> System.out.println("Wiring to IBAN " + bw.iban());
    }
}

process(new CreditCard("4242", 99.99));
process(new CryptoPayment("0xABCD", 0.05));

التحويل إلى Number لإجراء حسابات عامة

يتيح لك الصنف الأب Number إجراء عمليات رقمية عامة على أي نوع من الأعداد، وذلك بالتحويل التصاعدي إلى Number واستدعاء doubleValue().

import java.util.List;

List<Number> numbers = List.of(1, 2.5, 3L, 4.0f);

double sum = 0;
for (Number n : numbers) {
    sum += n.doubleValue(); // works for int, double, long, float
}
System.out.printf("Sum: %.1f%n", sum); // 10.5

أسلوب أداة للتحويل النوعي الآمن

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

import java.util.Optional;

public static <T> Optional<T> safeCast(Object obj, Class<T> clazz) {
    return clazz.isInstance(obj)
        ? Optional.of(clazz.cast(obj))
        : Optional.empty();
}

// Usage
Object val = "hello";
safeCast(val, String.class)
    .ifPresent(s -> System.out.println(s.toUpperCase())); // HELLO

safeCast(val, Integer.class)
    .ifPresentOrElse(
        n -> System.out.println(n),
        () -> System.out.println("Not an Integer") // prints this
    );

أخطاء شائعة ينبغي تجنبها

انتبه إلى أخطاء التحويل النوعي الشائعة التالية:

  • نسيان إجراء التحويل النوعي قبل القسمة: تعطي int/int عددًا صحيحًا دائمًا
  • إجراء تحويل تنازلي من دون التحقق باستخدام instanceof ← ClassCastException
  • الخلط بين التحويل التصاعدي (الآمن) والتحويل التنازلي (المحفوف بالمخاطر)
  • إجراء تحويل نوعي لأنواع الأصناف المُغلِّفة: (int) longVal مقابل longVal.intValue()
// Mistake 1: integer division
double avg = 7 / 2;            // 3.0 — WRONG
double fixed = 7.0 / 2;        // 3.5 — correct

// Mistake 2: unwrapping Long as int
Long bigId = 1234567890123L;
// int id = (int) bigId;  // compiles but truncates!
long id = bigId;           // correct

System.out.println(avg);   // 3.0
System.out.println(fixed); // 3.5
System.out.println(id);    // 1234567890123

تحقق سريع

ما ناتج هذه الشيفرة؟

int a = 7;
int b = 2;
double result = (double) a / b;
System.out.println(result);

مراجعة: التحويل النوعي عمليًا

أهم النقاط:

  • التحويل التصاعدي (من النوع الفرعي إلى النوع الأب) ضمني وآمن دائمًا
  • يتطلب التحويل التنازلي (من النوع الأب إلى النوع الفرعي) تحويلًا نوعيًا صريحًا؛ استخدم instanceof أولًا
  • تجمع مطابقة الأنماط مع instanceof بين التحقق والتحويل النوعي في تعبير واحد
  • حوّل البسط إلى double قبل القسمة لتجنب القطع الناتج عن قسمة الأعداد الصحيحة
  • استخدم مطابقة الأنماط في switch لتوجيه التنفيذ بوضوح حسب النوع
  • أنشئ أدوات safeCast للعمل مع Optional بدلًا من الاستثناءات

الأسئلة الشائعة

هل درس «تحويل الأنواع عمليًا» مجاني؟

نعم — نص درس «تحويل الأنواع عمليًا» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Java Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Java Academy 4 دروس في المجموع.

ماذا ستتعلم في «تحويل الأنواع عمليًا»؟

طبّق تحويل الأنواع في سيناريوهات واقعية، بما في ذلك الحسابات الرقمية وتسلسلات OOP الهرمية تتمرن على Java Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Java Academy؟

لا تُشترط خبرة سابقة. Java Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.

كم من الوقت يستغرق درس «تحويل الأنواع عمليًا»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Java Academy هذا؟

نعم. كل درس في Java Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. الأنواع البدائية مقابل الأنواع المرجعية
  2. تحويلات التوسيع والتضييق
  3. العامل instanceof
  4. تحويل الأنواع عمليًا
← العودة إلى Java Academy