0Pricing
Java Academy · درس

الدوال المجرّدة في Enums

سلوك خاص بكل ثابت

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

السلوك الخاص بكل ثابت

أحيانًا يحتاج كل ثابت في التعداد إلى سلوك مختلف، وليس إلى بيانات مختلفة فحسب.

تتيح لكم Java التصريح عن دالة مجردة في التعداد، ثم تجاوزها لكل ثابت. يُعرف هذا النمط باسم نمط جسم الدالة الخاص بالثابت.

public class Main {
    enum Operation {
        PLUS { public int apply(int a, int b) { return a + b; } },
        MINUS { public int apply(int a, int b) { return a - b; } };
        public abstract int apply(int a, int b);
    }
    public static void main(String[] args) {
        System.out.println(Operation.PLUS.apply(3, 4));
        System.out.println(Operation.MINUS.apply(10, 6));
    }
}

آلية العمل

يصبح كل ثابت يحتوي على جسم فئة فرعية مجهولة من التعداد.

وتجبر الدالة المجرّدة كل ثابت على توفير تنفيذ لها، ولذلك يضمن المصرّف اكتمال التنفيذ.

public class Main {
    enum Operation {
        TIMES { public int apply(int a, int b) { return a * b; } };
        public abstract int apply(int a, int b);
    }
    public static void main(String[] args) {
        // The constant is an instance of a generated subclass
        System.out.println(Operation.TIMES.getClass().getSimpleName().isEmpty()
            ? "anonymous subclass" : Operation.TIMES.apply(6, 7));
    }
}

آلة حاسبة كاملة

العمليات الحسابية الأربع كثوابت، ولكل منها جسم apply الخاص بها.

public class Main {
    enum Operation {
        PLUS  { public double apply(double a, double b) { return a + b; } },
        MINUS { public double apply(double a, double b) { return a - b; } },
        TIMES { public double apply(double a, double b) { return a * b; } },
        DIVIDE{ public double apply(double a, double b) { return a / b; } };
        public abstract double apply(double a, double b);
    }
    public static void main(String[] args) {
        double x = 6, y = 3;
        for (Operation op : Operation.values()) {
            System.out.printf("%s -> %.1f%n", op, op.apply(x, y));
        }
    }
}

دمج الحقول والسلوك

يمكنكم الجمع بين حقل، مثل رمز، وسلوك خاص بكل ثابت. يصف الحقل العملية، بينما تنفّذها الدالة.

public class Main {
    enum Operation {
        PLUS("+")  { public double apply(double a, double b) { return a + b; } },
        MINUS("-") { public double apply(double a, double b) { return a - b; } };
        private final String symbol;
        Operation(String symbol) { this.symbol = symbol; }
        public abstract double apply(double a, double b);
        @Override public String toString() { return symbol; }
    }
    public static void main(String[] args) {
        Operation op = Operation.PLUS;
        System.out.println("2 " + op + " 3 = " + op.apply(2, 3));
    }
}

لماذا لا نستخدم switch؟

يمكنكم تنفيذ apply باستخدام switch واحد على الثابت، لكن أسلوب الدالة المجرّدة أكثر أمانًا.

إذا أضفتم ثابتًا لاحقًا، فسيجبركم المصرّف على توفير جسمه. أما switch فقد يتجاهل الحالة الجديدة بصمت.

public class Main {
    enum Op {
        SQUARE { public int apply(int n) { return n * n; } },
        CUBE   { public int apply(int n) { return n * n * n; } };
        public abstract int apply(int n);
    }
    public static void main(String[] args) {
        System.out.println(Op.SQUARE.apply(5));
        System.out.println(Op.CUBE.apply(3));
    }
}

الدوال الملموسة إلى جانب المجرّدة

يمكن للتعداد الجمع بين الدوال المجرّدة والملموسة. ضعوا المنطق المشترك في دالة ملموسة، واتركوا المنطق المتغير مجرّدًا.

public class Main {
    enum Shape {
        CIRCLE { public double area(double x) { return Math.PI * x * x; } },
        SQUARE { public double area(double x) { return x * x; } };
        public abstract double area(double x);
        public String report(double x) { return this + " area = " + area(x); }
    }
    public static void main(String[] args) {
        System.out.println(Shape.CIRCLE.report(2));
    }
}

تعدادات الاستراتيجيات

من التحسينات الممكنة استخدام تعداد الاستراتيجية، حيث تفوّض الثوابت التنفيذ إلى تعداد استراتيجية متداخل بدلًا من التجاوز مباشرة.

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

public class Main {
    enum PayType {
        WEEKDAY { int overtime(int mins) { return mins; } },
        WEEKEND { int overtime(int mins) { return mins * 2; } };
        abstract int overtime(int mins);
        int pay(int mins) { return mins + overtime(Math.max(0, mins - 480)); }
    }
    public static void main(String[] args) {
        System.out.println("Weekend pay: " + PayType.WEEKEND.pay(540));
    }
}

تعداد بواجهة وأجسام

يمكنكم الجمع بين واجهة وأجسام خاصة بالثوابت لتحقيق أقصى قدر من تعدد الأشكال.

public class Main {
    interface Command { String run(); }
    enum Action implements Command {
        START { public String run() { return "starting..."; } },
        STOP  { public String run() { return "stopping..."; } };
    }
    public static void main(String[] args) {
        for (Action a : Action.values()) System.out.println(a.run());
    }
}

الوصول إلى الحقول من الأجسام

يمكن للجسم الخاص بالثابت قراءة حقول الثابت نفسه، لأن كل جسم يعمل في سياق ذلك المثيل.

public class Main {
    enum Tax {
        STANDARD(0.20) { double apply(double amt) { return amt * (1 + rate); } },
        REDUCED(0.05)  { double apply(double amt) { return amt * (1 + rate); } };
        protected final double rate;
        Tax(double rate) { this.rate = rate; }
        abstract double apply(double amt);
    }
    public static void main(String[] args) {
        System.out.printf("%.2f%n", Tax.STANDARD.apply(100));
    }
}

افتراضي ثم تجاوز

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

public class Main {
    enum Notifier {
        EMAIL,
        SMS { String send(String m) { return "SMS: " + m; } };
        String send(String m) { return "EMAIL: " + m; }
    }
    public static void main(String[] args) {
        System.out.println(Notifier.EMAIL.send("hi"));
        System.out.println(Notifier.SMS.send("hi"));
    }
}

آلة حالات صغيرة

يبرز السلوك الخاص بكل ثابت في آلات الحالات؛ إذ يعرف كلٌّ من الحالات انتقاله الخاص.

public class Main {
    enum State {
        IDLE    { State next() { return RUNNING; } },
        RUNNING { State next() { return DONE; } },
        DONE    { State next() { return DONE; } };
        abstract State next();
    }
    public static void main(String[] args) {
        State s = State.IDLE;
        for (int i = 0; i < 3; i++) { System.out.println(s); s = s.next(); }
        System.out.println(s);
    }
}

تحقق سريع

اختبروا فهمكم للدوال المجرّدة في التعدادات.

مراجعة

تعلّمتم السلوك الخاص بكل ثابت:

  • صرّحوا عن دالة مجردة وتجاوزوها في جسم كل ثابت.
  • يصبح كل ثابت فئة فرعية مجهولة.
  • يفرض المصرّف اكتمال التنفيذ، مما يجعله أفضل من switch.
  • يمكنكم دمج الحقول والقيم الافتراضية الملموسة والواجهات لإنشاء تعداد غني بالوظائف.

التالي هو EnumSet عالي الأداء.

public class Main {
    enum E { A { int v() { return 1; } }; abstract int v(); }
    public static void main(String[] args) {
        System.out.println("Abstract enum recap: " + E.A.v());
    }
}

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

هل درس «الدوال المجرّدة في Enums» مجاني؟

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

ماذا ستتعلم في «الدوال المجرّدة في Enums»؟

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

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

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

كم من الوقت يستغرق درس «الدوال المجرّدة في Enums»؟

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

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

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

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

  1. Enums مع الحقول والدوال
  2. الدوال المجرّدة في Enums
  3. EnumSet
  4. EnumMap
← العودة إلى Java Academy