توجد طريقة قيم في التعداد تُستخدم لإنشاء مصفوفة بالترتيب المحدد بواسطة التعداد، والتي يمكن استخدامها للاجتياز. جميع فئات التعداد المخصصة لدينا ترث من java.lang.Enum ولها الوظائف التالية في الأمثلة:
انسخ رمز الكود كما يلي:
//: تعداد/EnumClass.java
// إمكانيات فئة التعداد
import static net.mindview.util.Print.*;
تعداد الشجيرات { الأرض، الزحف، المعلقة }
الطبقة العامة EnumClass {
public static void main(String[] args) {
for(Shrubbery s : Shrubbery.values()) {
print(s + "ordinal:" + s.ordinal());
printnb(s.compareTo(Shrubbery.CRAWLING) + " ");
printnb(s.equals(Shrubbery.CRAWLING) + " ");
print(s == Shrubbery.CRAWLING);
طباعة (s.getDeclaringClass())؛
طباعة(s.name());
مطبعة("----------------------")؛
}
// إنتاج قيمة التعداد من اسم السلسلة:
for(String s : "HANGING CRAWLING GROUND".split(" ")) {
شجيرة الشجيرات = Enum.valueOf(Shrubbery.class, s);
طباعة (شجيرة)؛
}
}
} /* الإخراج:
الترتيب الأرضي: 0
-1 كاذبة كاذبة
فئة الشجيرات
كان جوشوا بلوخ مفيدًا جدًا في تطوير هذا الفصل.
أرضي
-----------------------
الزحف الترتيبي: 1
صحيح صحيح
فئة الشجيرات
الزحف
-----------------------
تعليق الترتيبي: 2
كاذبة كاذبة
فئة الشجيرات
معلقة
-----------------------
معلقة
الزحف
أرضي
*///:~
يمكننا أيضًا استخدام مراجع التعداد الثابت:
انسخ رمز الكود كما يلي:
//: تعداد/Spiciness.java
الحزمة المذكورة؛
التعداد العام التوابل {NOT، MILD، MEDIUM، HOT، FLAMING} ///:~
//: تعداد/Burrito.java
الحزمة المذكورة؛
import static enumerated.Spiciness.*;
الطبقة العامة بوريتو {
درجة البهارات
بوريتو العامة (درجة البهارات) { this.degree = Degree;}
public String toString() { return "بوريتو هو"+ درجة;}
public static void main(String[] args) {
System.out.println(new Burrito(NOT));
System.out.println(new Burrito(MEDIUM));
System.out.println(new Burrito(HOT));
}
} /* الإخراج:
بوريتو ليس كذلك
بوريتو متوسط
بوريتو ساخن
*///:~
بالإضافة إلى إضافة أساليب إلى التعداد، والتي لا يمكن توريثها، يمكن التعامل مع التعداد كفئة عامة، مما يعني أنه يمكنك إضافة أساليب إلى التعداد، ويمكنك أيضًا تحديد الطريقة الرئيسية في التعداد:
انسخ رمز الكود كما يلي:
//: تعداد/OzWitch.java
// السحرة في أرض أوز.
import static net.mindview.util.Print.*;
التعداد العام OzWitch {
// يجب تعريف المثيلات أولاً قبل الطرق:
WEST("الآنسة جولتش، المعروفة أيضًا باسم ساحرة الغرب الشريرة"),NORTH("غليندا، ساحرة الشمال الطيبة"),EAST("ساحرة الشرق الشريرة، مرتدية الياقوتة" + "النعال، التي تم سحقها بواسطة منزل دوروثي"),SOUTH("جيد بالاستدلال ولكنه مفقود");
وصف السلسلة الخاصة؛
// يجب أن يكون المنشئ عبارة عن حزمة أو وصول خاص:
خاص OzWitch (وصف السلسلة) {
this.description = description;
}
سلسلة getDescription() العامة { وصف الإرجاع }
public static void main(String[] args) {
لـ (ساحرة OzWitch: OzWitch.values())
طباعة (ساحرة + ":" + witch.getDescription())؛
}
} /* الإخراج:
الغرب: الآنسة جولتش، الملقبة بساحرة الغرب الشريرة
الشمال: غليندا، ساحرة الشمال الطيبة
الشرق: ساحرة الشرق الشريرة، مرتدية النعال الياقوتية، يتم سحقها من قبل منزل دوروثي
الجنوب: جيد بالاستدلال، لكنه مفقود
*///:~
انسخ رمز الكود كما يلي:
//: تعداد/SpaceShip.java
التعداد العام سفينة الفضاء {
الكشافة، البضائع، النقل، الطراد، السفينة الحربية، السفينة الأم؛
سلسلة عامة إلى سلسلة () {
معرف السلسلة = الاسم ()؛
سلسلة أقل = id.substring(1).toLowerCase();
إرجاع id.charAt(0) + Lower;
}
public static void main(String[] args) {
ل(SpaceShip s : القيم()) {
System.out.println(s);
}
}
} /* الإخراج:
كشاف
البضائع
ينقل
كروزر
سفينة حربية
الأم
*///:~
التعدادات في عبارات التبديل دور مهم للتعدادات في عبارات التبديل عادةً ما تعمل عبارات التبديل فقط على القيم الصحيحة، ولكن هناك ترتيبًا مدمجًا للأعداد الصحيحة في التعدادات، لذلك يمكن تحديد ترتيب المثيلات من خلال بعض الطرق. لذلك يمكن استخدام التعدادات في عبارات التبديل:
انسخ رمز الكود كما يلي:
//: تعداد/TrafficLight.java
// التعداد في بيانات التبديل.
import static net.mindview.util.Print.*;
// تحديد نوع التعداد:
إشارة التعداد {أخضر، أصفر، أحمر، }
فئة عامة TrafficLight {
لون الإشارة = Signal.RED؛
تغيير الفراغ العام () {
التبديل (اللون) {
// لاحظ أنه ليس من الضروري أن تقول Signal.RED
// في بيان الحالة:
الحالة الحمراء: اللون = Signal.GREEN؛
استراحة؛
الحالة الخضراء: اللون = الإشارة. أصفر؛
استراحة؛
الحالة الصفراء: اللون = الإشارة.أحمر؛
استراحة؛
}
}
سلسلة عامة إلى سلسلة () {
إرجاع "إشارة المرور هي" + اللون؛
}
public static void main(String[] args) {
TrafficLight t = new TrafficLight();
ل(int i = 0; i < 7; i++) {
طباعة (ر)؛
t.change();
}
}
} /* الإخراج:
إشارة المرور باللون الأحمر
إشارة المرور خضراء
إشارة المرور صفراء
إشارة المرور باللون الأحمر
إشارة المرور خضراء
إشارة المرور صفراء
إشارة المرور باللون الأحمر
*///:~
سر القيم () على الرغم من أننا استخدمنا طريقة القيم من قبل، إلا أننا إذا نظرنا إلى Enum لا نجد طريقة القيم، فهل هناك طرق مخفية أخرى؟ يمكننا التحقق من ذلك باستخدام رمز انعكاس بسيط:
انسخ رمز الكود كما يلي:
//: تعداد/Reflection.java
// تحليل التعدادات باستخدام الانعكاس.
import java.lang.reflect.*;
import java.util.*;
import net.mindview.util.*;
import static net.mindview.util.Print.*;
التعداد استكشاف { هنا، هناك }
انعكاس الطبقة العامة {
تحليل Set<String> العام الثابت(Class<?> enumClass) {
print("----- تحليل " + enumClass + " -----");
طباعة ("الواجهات:")؛
لـ (النوع t: enumClass.getGenericInterfaces())
طباعة (ر)؛
طباعة("القاعدة:" + enumClass.getSuperclass());
طباعة("الطرق:");
Set<String>methods = new TreeSet<String>();
من أجل (الطريقة م: enumClass.getMethods())
methods.add(m.getName());
طباعة (طرق)؛
طرق العودة
}
public static void main(String[] args) {
Set<String> exploreMethods = Analysis(Explore.class);
Set<String> enumMethods = Analysis(Enum.class);
طباعة("Explore.containsAll(Enum)؟" +
exploreMethods.containsAll(enumMethods));
printnb("Explore.removeAll(Enum):");
exploreMethods.removeAll(enumMethods);
طباعة(exploreMethods);
// قم بفك كود التعداد:
OSExecute.command("استكشاف javap");
}
} /* الإخراج:
----- تحليل الفصل استكشاف -----
واجهات:
القاعدة: فئة java.lang.Enum
طُرق:
[compareTo، يساوي، getClass، getDeclaringClass، hashCode، name، notify، notifyAll، ordinal، toString، valueOf،values، wait]
----- تحليل فئة java.lang.Enum -----
واجهات:
java.lang.Comparable<E>
واجهة java.io.Serializable
القاعدة: فئة java.lang.Object
طُرق:
[compareTo، يساوي، getClass، getDeclaringClass، hashCode، name، notify، notifyAll، ordinal، toString، valueOf، wait]
Explore.containsAll(Enum) صحيح؟
Explore.removeAll(Enum): [القيم]
تم تجميعها من "Reflection.java"
استكشاف الطبقة النهائية يمتد java.lang.Enum{
النهائي العام الثابت استكشف هنا؛
النهائي العام الثابت اكتشف هناك؛
استكشاف القيم النهائية العامة الثابتة [] () ؛
استكشاف القيمة الثابتة العامة (java.lang.String)؛
ثابت {}؛
}
*///:~
يمكننا أن نرى أن طريقة القيم تتم إضافتها بواسطة المترجم. تتم إضافة طريقة valueOf أيضًا بواسطة المترجم عند إنشاء التعداد، ولكن هناك أيضًا طريقة valueOf في فئة Enum، ولكن هذه الطريقة تحتوي على معلمتين، بينما تحتوي طريقة valueOf التي أضافها المترجم على معلمة واحدة فقط. يتم تفسير التعدادات على أنها نهائية من قبل المترجم، لذلك لا يمكن وراثة التعدادات. نظرًا لأن طريقة القيم هي طريقة ثابتة تمت إضافتها بواسطة المترجم، إذا قمت بإلقاء التعداد إلى Enum، فلن تكون طريقة القيم متاحة، ولكن هناك طريقة getEnumConstants في Class، لذلك على الرغم من أن طريقة القيم هي غير متوفر في Enum، ولكن لا يزال بإمكانك الحصول على نسخة التعداد من خلال كائن Class:
انسخ رمز الكود كما يلي:
//: تعداد/UpcastEnum.java
// لا توجد طريقة للقيم () إذا قمت بتحديث التعداد
التعداد البحث { هنا، يون }
الطبقة العامة UpcastEnum {
public static void main(String[] args) {
بحث[] فالس = Search.values();
التعداد e = Search.HITHER;
// e.values(); // لا توجد قيم() في التعداد
for(Enum en : e.getClass().getEnumConstants())
System.out.println(en);
}
} /* الإخراج:
هنا
يون
*///:~
التنفيذ بدون وراثة لأن أنواع التعداد التي نحددها كلها ترث من java.lang.Enum، ولا تدعم Java الوراثة المتعددة، لذلك لا يتم إنشاء التعدادات من خلال الوراثة، ولكن يمكن إنشاء التعدادات عن طريق وراثة واجهة واحدة أو أكثر:
انسخ رمز الكود كما يلي:
//: enumerated/cartoons/EnumImplementation.java
// يمكن للتعداد تنفيذ واجهة
تعداد الحزمة.الرسوم المتحركة؛
import java.util.*;
import net.mindview.util.*;
التعداد CartoonCharacter بتنفيذ Generator<CartoonCharacter> {
سلابي، شجاع، قوي، سخيف، نطاط، جوزي، بوب؛
راند عشوائي خاص = عشوائي جديد (47)؛
شخصية الرسوم المتحركة العامة التالية () {
قيم الإرجاع () [rand.nextInt (القيم (). الطول)]؛
}
}
فئة عامة EnumImplementation {
public static <T> void printNext(Generator<T> rg) {
System.out.print(rg.next() + ", ");
}
public static void main(String[] args) {
// اختر أي مثيل:
CartoonCharacter cc = CartoonCharacter.BOB;
ل(int i = 0; i < 10; i++)
printNext(cc);
}
} /* الإخراج:
بوب، بونتشي، بوب، سبانكي، جوزي، بونشي، سلابي، جوزي، جوزي، سلابي،
*///:~
التحديد العشوائي في العديد من الأمثلة التي سنعرضها لاحقًا، سنختار كائنات عشوائيًا من مثيلات التعداد، وسنقوم بإنشاء فئة عامة لتنفيذ ذلك:
انسخ رمز الكود كما يلي:
//: net/mindview/util/Enums.java
الحزمة net.mindview.util;
import java.util.*;
تعدادات الفئة العامة {
راند عشوائي ثابت خاص = عشوائي جديد (47) ؛
عام ثابت <T يمتد Enum<T>> T عشوائي(Class<T> ec) {
إرجاع عشوائي (ec.getEnumConstants());
}
عام ثابت <T> T عشوائي (قيم T []) {
قيم الإرجاع[rand.nextInt(values.length)];
}
} ///:~
انسخ رمز الكود كما يلي:
//: تعداد/RandomTest.java
import net.mindview.util.*;
enum النشاط { الجلوس، الاستلقاء، الوقوف، القفز، الجري، المراوغة، القفز، السقوط، الطيران }
اختبار عشوائي للفئة العامة {
public static void main(String[] args) {
ل(int i = 0; i < 20; i++)
System.out.print(Enums.random(Activity.class) + " ");
}
} /* الإخراج:
يقف الطيران يركض يقف يقف يركض يقف مستلقيا المراوغة يجلس يركض قفز قفز قفز ركض يقف مستلقيا يسقط يركض يطير الكذب
*///:~
لا يمكن توريث استخدام الواجهات لتنظيم التعدادات، مما يسبب لنا الإزعاج أحيانًا، لأننا في بعض الأحيان نريد توسيع عدد التعدادات من خلال الوراثة، وأحيانًا نحتاج إلى تجميع التعدادات. بالنسبة للأخيرة، يمكننا تحديد التعدادات المجمعة داخل الواجهة، ثم إنشاء التعداد عن طريق الوراثة من هذه الواجهة، كما يلي، لدينا فئات غذائية مختلفة يجب إنشاؤها كتعدادات، ولكننا بحاجة إلى تعريف كل فئة على أنها أنواع. من المواد الغذائية على النحو التالي:
انسخ رمز الكود كما يلي:
//: تعداد/قائمة/Food.java
// تصنيف فرعي للتعدادات داخل الواجهات.
الحزمة المذكورة. القائمة؛
الواجهة العامة للطعام {enum Appetizer تنفذ الطعام {SALAD, SOUP, SPRING_ROLLS;}
enum MainCourse تنفذ الطعام {LASAGNE, BURRITO, PAD_THAI,LENTILS, HUMMOUS, VINDALOO;}
enum أدوات الحلوى الغذائية {TIRAMISU, GELATO, BLACK_FOREST_CAKE,FRUIT, CREME_CARAMEL;}
enum أدوات القهوة الطعام {BLACK_COFFEE, DECAF_COFFEE, ESPRESSO,LATTE, CAPPUCCINO, TEA, HERB_TEA;}
} ///:~
نظرًا لأن كل تعداد يتم تعريفه على أنه تنفيذ لواجهة، فإن كل تعداد يكون من النوع Food، كما يلي:
انسخ رمز الكود كما يلي:
//: enumerated/menu/TypeOfFood.java
الحزمة المذكورة. القائمة؛
import static enumerated.menu.Food.*;
الطبقة العامة TypeOfFood {
public static void main(String[] args) {
الغذاء الغذاء = فاتح الشهية.SALAD؛
food = MainCourse.LASAGNE;
الغذاء = الحلوى.جيلاتو؛
الغذاء = القهوة.كابتشينو؛
}
} ///:~
لكن الواجهات لا يمكنها العمل على أنواع متعددة مثل التعدادات، لذلك إذا كنت بحاجة إلى تعداد للتعدادات، فيمكنك تغليف مثيل لكل نوع تعداد في التعداد:
انسخ رمز الكود كما يلي:
//: تعداد/القائمة/Course.java
الحزمة المذكورة. القائمة؛
import net.mindview.util.*;
دورة التعداد العام {
APPETIZER(Food.Appetizer.class)،MAINCOURSE(Food.MainCourse.class)،DESSERT(Food.Dessert.class)،COFFEE(Food.Coffee.class);
قيم الغذاء الخاصة[]؛
دورة خاصة (فئة <؟ تمتد إلى نوع الطعام>) {
القيم = kind.getEnumConstants();
}
اختيار عشوائي للأغذية العامة () {
إرجاع Enums.random(values);
}
} ///:~
يستخدم كل تعداد كائن Class كمعلمة منشئة مقابلة، ويمكننا استخدام getEnumConstants من هذه المعلمة للحصول على مثيل التعداد، ويمكن استخدام هذا المثيل في طريقة RandomSelection لإنشاء وجبات عشوائية:
انسخ رمز الكود كما يلي:
//: تعداد/قائمة/Meal.java
الحزمة المذكورة. القائمة؛
وجبة الطبقة العامة {
public static void main(String[] args) {
ل(int i = 0; i < 5; i++) {
for(دورة الدورة: Course.values()) {
الغذاء الغذاء = Course.randomSelection();
System.out.println(food);
}
System.out.println("---");
}
}
} /* الإخراج:
SPRING_ROLLS
فيندالو
الفاكهة
قهوة منزوعة الكافيين
---
حساء
فيندالو
الفاكهة
شاي
---
سلطة
بوريتو
الفاكهة
شاي
---
سلطة
بوريتو
كريم_كراميل
لاتيه
---
حساء
بوريتو
تيراميسو
إسبرسو
---
*///:~
فيما يلي تطبيق أكثر إحكاما:
انسخ رمز الكود كما يلي:
//: تعداد/SecurityCategory.java
// تصنيف فرعي أكثر إيجازًا للتعدادات.
import net.mindview.util.*;
التعداد فئة الأمان {
STOCK(Security.Stock.class)، BOND(Security.Bond.class);
قيم الأمان[]؛
SecurityCategory(الفئة<? تمتد الأمان> النوع) {
القيم = kind.getEnumConstants();
}
أمان الواجهة {
enum Stock يطبق الأمان {SHORT, LONG, MARGIN}
enum Bond ينفذ الأمان { MUNICIPAL, JUNK }
}
اختيار عشوائي للأمان العام () {
إرجاع Enums.random(values);
}
public static void main(String[] args) {
ل(int i = 0; i < 10; i++) {
فئة SecurityCategory = Enums.random(SecurityCategory.class);
System.out.println(الفئة + ": " +
class.randomSelection());
}
}
} /* الإخراج:
السند: البلدية
السند: البلدية
المخزون: الهامش
المخزون: الهامش
السند: غير المرغوب فيه
المخزون: قصير
المخزون: طويل
المخزون: طويل
السند: البلدية
السند: غير المرغوب فيه
*///:~
انسخ رمز الكود كما يلي:
//: تعداد/قائمة/Meal2.java
الحزمة المذكورة. القائمة؛
import net.mindview.util.*;
التعداد العام وجبة 2 {
APPETIZER(Food.Appetizer.class)،MAINCOURSE(Food.MainCourse.class)،DESSERT(Food.Dessert.class)،COFFEE(Food.Coffee.class);
قيم الغذاء الخاصة[]؛
وجبة خاصة 2 (الفئة <؟ تمتد إلى نوع الطعام>) {
القيم = kind.getEnumConstants();
}
الواجهة العامة للأغذية {
enum المقبلات تنفذ الطعام {SALAD, SOUP, SPRING_ROLLS;}
enum MainCourse تنفذ الطعام {LASAGNE, BURRITO, PAD_THAI,LENTILS, HUMMOUS, VINDALOO;}
enum أدوات الحلوى الغذائية {TIRAMISU, GELATO, BLACK_FOREST_CAKE,FRUIT, CREME_CARAMEL;}
enum أدوات القهوة الطعام {BLACK_COFFEE, DECAF_COFFEE, ESPRESSO,LATTE, CAPPUCCINO, TEA, HERB_TEA;}
}
اختيار عشوائي للأغذية العامة () {
إرجاع Enums.random(values);
}
public static void main(String[] args) {
ل(int i = 0; i < 5; i++) {
ل(وجبة Meal2: Meal2.values()) {
الغذاء الغذاء =meal.randomSelection();
System.out.println(food);
}
System.out.println("---");
}
}
} /* نفس إخراج Meal.java *///:~
استخدم EnumSet بدلاً من العلامات. تمت إضافة EnumSet في Java SE5 لدمج التعدادات والمجموعات لاستبدال إشارات البت المستندة إلى الأعداد الصحيحة. عادةً ما تُستخدم أعلام البت للإشارة إلى تبديل نوع ما من المعلومات، ولكن في التعليمات البرمجية، يتم تشغيل البتات بدلاً من مفاهيم ذات معنى، لذلك ليس من السهل فهمها. إن EnumSet أسرع من إشارات البت، فهو يستخدم مسافة طويلة داخليًا لتمثيل ناقل البت، ومن ثم يمكنك استخدام لغة أكثر مفاهيمية لتمثيل تبديل بت معين دون القلق بشأن الكفاءة. يجب أن تأتي العناصر الموجودة في EnumSet من نفس التعداد. ما يلي يحدد تعداد موضع التنبيه:
انسخ رمز الكود كما يلي:
//: تعداد/AlarmPoints.java
الحزمة المذكورة؛
التعداد العام نقاط الإنذار {STAIR1, STAIR2, LOBBY, OFFICE1, OFFICE2, OFFICE3,OFFICE4, BATHROOM, UTILITY, KITCHEN} ///:~
ثم استخدم فئة EnumSet لتتبع حالة التنبيه:
انسخ رمز الكود كما يلي:
//: تعداد/EnumSets.java
// العمليات على EnumSets
الحزمة المذكورة؛
import java.util.*;
import static enumerated.AlarmPoints.*;
import static net.mindview.util.Print.*;
فئة عامة EnumSets {
public static void main(String[] args) {
EnumSet<AlarmPoints> point = EnumSet.noneOf(AlarmPoints.class);
point.add(BATHROOM);
طباعة (نقاط)؛
point.addAll(EnumSet.of(STAIR1, STAIR2, KITCHEN));
طباعة (نقاط)؛
point = EnumSet.allOf(AlarmPoints.class);
point.removeAll(EnumSet.of(STAIR1, STAIR2, KITCHEN));
طباعة (نقاط)؛
point.removeAll(EnumSet.range(OFFICE1, OFFICE4));
طباعة (نقاط)؛
Points = EnumSet.comlementOf(points);
طباعة (نقاط)؛
}
} /* الإخراج:
[حمام]
[الدرج 1، الدرج 2، الحمام، المطبخ]
[الردهة، المكتب 1، المكتب 2، المكتب 3، المكتب 4، الحمام، المرافق]
[الردهة، الحمام، المرافق]
[الدرج 1، الدرج 2، المكتب 1، المكتب 2، المكتب 3، المكتب 4، المطبخ]
*///:~
EnumSet مبني على نوع طويل ويحتوي على 64 بت، فماذا لو تجاوز نوع التعداد لدينا هذا الرقم؟
انسخ رمز الكود كما يلي:
//: تعداد/BigEnumSet.java
import java.util.*;
فئة عامة BigEnumSet {
التعداد الكبير { A0، A1، A2، A3، A4، A5، A6، A7، A8، A9، A10، A11، A12، A13، A14، A15، A16، A17، A18، A19، A20، A21، A22، A23 ، A24، A25، A26، A27، A28، A29، A30، A31، A32،
A33، A34، A35، A36، A37، A38، A39، A40، A41، A42، A43، A44، A45، A46، A47، A48، A49، A50، A51، A52، A53، A54، A55، A56، A57، A58، A59، A60، A61، A62، A63، A64، A65،
A66، A67، A68، A69، A70، A71، A72، A73، A74، A75}
public static void main(String[] args) {
EnumSet<Big> bigEnumSet = EnumSet.allOf(Big.class);
System.out.println(bigEnumSet);
}
} /* الإخراج:
[A0، A1، A2، A3، A4، A5، A6، A7، A8، A9، A10، A11، A12، A13، A14، A15، A16، A17، A18، A19، A20، A21، A22، A23، A24 ، A25، A26، A27، A28، A29، A30، A31، A32، A33، A34، A35، A36، A37، A38، A39، A40، A41، A42، A43، A44، A45، A46، A47، A48، A49، A50، A51، A52، A53، A54، A55، A56، A57، A58، A59، A60، A61، A62، A63، A64، A65، A66، A67، A68، A69، A70، A71، A72، A73، A74، A75]
*///:~
يمكننا أن نرى أن البرنامج يعمل بشكل طبيعي، لذلك من المحتمل جدًا أن تتم إضافة نوع طويل داخليًا للمساعدة في استيعاب نوع التعداد باستخدام EnumMap.
EnumMap هو نوع خاص من الخريطة، وقيمة مفتاحه يمكن أن تكون فقط من النوع الموجود في نفس التعداد، ولهذا السبب، يمكن تنفيذ EnumMap داخليًا من خلال مصفوفة، وهو أمر فعال للغاية.
انسخ رمز الكود كما يلي:
//: تعداد/EnumMaps.java
// أساسيات EnumMaps.
الحزمة المذكورة؛
import java.util.*;
import static enumerated.AlarmPoints.*;
import static net.mindview.util.Print.*;
أمر الواجهة {إجراء باطل ()}
الطبقة العامة EnumMaps {
public static void main(String[] args) {
EnumMap<AlarmPoints,Command> em = new EnumMap<AlarmPoints,Command>(AlarmPoints.class);
em.put(KITCHEN, new Command() {
إجراء باطل عام () {طباعة ("حريق المطبخ!") ؛
});
em.put(الحمام، الأمر الجديد() {
إجراء باطل عام () {طباعة ("تنبيه الحمام!" })؛
});
for(Map.Entry<AlarmPoints,Command> e : em.entrySet()) {
printnb(e.getKey() + ":");
e.getValue().action();
}
حاول { // إذا لم تكن هناك قيمة لمفتاح معين:
em.get(UTILITY).action();
} قبض (استثناء ه) {
طباعة (ه)؛
}
}
} /* الإخراج:
الحمام: تنبيه الحمام!
المطبخ: حريق المطبخ!
java.lang.NullPointerException
*///:~
طرق ثابتة محددة تتميز تعدادات Java بميزة مثيرة للاهتمام للغاية، وهي أنه يمكن تعريف سلوكيات مختلفة لكل مثيل تعداد، ومن أجل تحقيق ذلك، نحدد طريقة مجردة واحدة أو أكثر كجزء من التعداد، ثم نحدد سلوكيات مختلفة لكل منها. طريقة تعريف مثيل التعداد:
انسخ رمز الكود كما يلي:
//: تعداد/ConstantSpecificMethod.java
import java.util.*;
استيراد java.text.*;
التعداد العام ConstantSpecificMethod {
DATE_TIME {String getInfo() {return DateFormat.getDateInstance().format(new Date());}},
CLASSPATH {String getInfo() {return System.getenv("CLASSPATH");}},
VERSION {String getInfo() {return System.getProperty("java.version");}};
سلسلة مجردة getInfo();
public static void main(String[] args) {
لـ (ConstantSpecificMethod csm: القيم ())
System.out.println(csm.getInfo());
}
} /* (تنفيذ لرؤية الإخراج) *///:~
يبدو أن الكود أعلاه عالق لأن كل عنصر تعداد هو عنصر مختلف، وجميع العناصر ترث من الفئة الأساسية ConstantSpecificMethod، لكننا لا نستطيع حقًا فهمها بهذه الطريقة، لأننا لا نستطيع التعامل مع عناصر التعداد كأنواع:
انسخ رمز الكود كما يلي:
//: تعداد/NotClasses.java
// {Exec: javap -c LikeClasses}
import static net.mindview.util.Print.*;
تعداد LikeClasses {WINKEN { سلوك void() { print("Behavior1" } },BLINKEN { سلوك void() { print("Behavior2" } },NOD { سلوك void() { print("Behavior3") } };
سلوك الفراغ المجرد () ؛
}
الطبقة العامة NotClasses {
// void f1(مثيل LikeClasses.WINKEN) {} // كلا
} /* الإخراج:
تم تجميعها من "NotClasses.java"
فئة مجردة LikeClasses تمتد java.lang.Enum{
نهائي عام ثابت LikeClasses WINKEN؛
نهائي عام ثابت LikeClasses BLINKEN؛
نهائي عام ثابت LikeClasses NOD؛
...
*///:~
خذ بعين الاعتبار مثالًا آخر، هناك قائمة غسيل سيارات يختار العملاء خدمات مختلفة بناءً على قوائم مختلفة، ويمكنك استخدام أساليب ثابتة محددة لربط القائمة بالخدمات، واستخدام EnumSet للحفاظ على اختيارات العميل، كما يلي:
انسخ رمز الكود كما يلي:
//: تعداد/CarWash.java
import java.util.*;
import static net.mindview.util.Print.*;
غسيل سيارات فئة عامة {
دورة التعداد العام {UNDERBODY {void action() { print("رش الجزء السفلي" }});
WHEELWASH {void action() { print("غسل العجلات" }});
الغسيل المسبق {void action() { print("تخفيف الأوساخ" }});
BASIC {void action() { print("الغسيل الأساسي" }});
HOTWAX {void action() { print("تطبيق الشمع الساخن" }},
شطف {إجراء باطل () {طباعة ("الشطف" }})؛
BLOWDRY {void action() { print("تجفيف" }});
عمل باطلة مجردة () ؛
}
EnumSet<Cycle>cycles = EnumSet.of(Cycle.BASIC, Cycle.RINSE);
إضافة باطلة عامة (دورة دورة) {cycles.add(cycle));
غسيل السيارات باطلة عامة () {
لـ (الدورة ج: دورات)
c.action();
}
سلسلة عامة toString() {returncycles.toString()};
public static void main(String[] args) {
غسيل السيارات = غسيل السيارات الجديد ()؛
طباعة (غسل)؛
wash.washCar();
// ترتيب الجمع غير مهم:
wash.add(Cycle.BLOWDRY);
wash.add(Cycle.BLOWDRY); // تم تجاهل التكرارات
wash.add(Cycle.RINSE);
wash.add(Cycle.HOTWAX);
طباعة (غسل)؛
wash.washCar();
}
} /* الإخراج:
[أساسي، شطف]
الغسل الأساسي
الشطف
[أساسي، شمع ساخن، شطف، مجفف]
الغسل الأساسي
تطبيق الشمع الساخن
الشطف
تجفف بالهواء
*///:~
يمكننا أيضًا تجاوز الطرق الثابتة الافتراضية المحددة بدلاً من استخدام الطرق المجردة الموروثة، كما يلي:
انسخ رمز الكود كما يلي:
//: تعداد/OverrideConstantSpecific.java
import static net.mindview.util.Print.*;
التعداد العام OverrideConstantSpecific {
NUT, BOLT,WASHER {void f() { print("طريقة التجاوز" }});
باطلة و() { طباعة ("السلوك الافتراضي" })؛
public static void main(String[] args) {
for(OverrideConstantSpecific ocs :values()) {
printnb(ocs + ":");
ocs.f();
}
}
} /* الإخراج:
NUT: السلوك الافتراضي
بولت: السلوك الافتراضي
الغسالة: طريقة التجاوز
*///:~
في بعض الأحيان نرغب في تمرير طلبات محددة في السلسلة، ويمكن بسهولة معرفة أن كائنًا ما في السلسلة يمكنه التعامل مع الطلب باستخدام طرق ثابتة محددة، وفيما يلي مثال على معالجة رسائل البريد الإلكتروني:
انسخ رمز الكود كما يلي:
//: تعداد/PostOffice.java
// نمذجة مكتب البريد.
الأنواع المذكورة 743
import java.util.*;
import net.mindview.util.*;
import static net.mindview.util.Print.*;
بريد الطبقة {
// NO يقلل من احتمالية الاختيار العشوائي:
تعداد التسليم العام {YES,NO1,NO2,NO3,NO4,NO5}
قابلية المسح الضوئي {UNSCANNABLE,YES1,YES2,YES3,YES4}
سهولة قراءة التعداد {ILLEGIBLE,YES1,YES2,YES3,YES4}
عنوان التعداد {INCORRECT,OK1,OK2,OK3,OK4,OK5,OK6}
تعداد عنوان الإرجاع {MISSING,OK1,OK2,OK3,OK4,OK5}
التسليم العام التسليم العام؛
قابلية المسح؛
سهولة القراءة؛
عنوان العنوان؛
عنوان الإرجاع returnAddress;
عداد طويل ثابت = 0؛
معرف طويل = عداد++؛
سلسلة عامة toString () {إرجاع "البريد" + المعرف }
تفاصيل السلسلة العامة () {
return toString() + "، التسليم العام: " + publicDelivery + "، إمكانية مسح العنوان: " + إمكانية المسح + "، إمكانية قراءة العنوان: " + إمكانية القراءة +
"، عنوان العنوان: " + عنوان + "، عنوان المرسل: " + returnAddress؛
}
// إنشاء بريد اختباري:
البريد العام الثابت RandomMail() {
البريد م = بريد جديد ()؛
m.generalDelivery= Enums.random(generalDelivery.class);
m.scannability = Enums.random(Scannability.class);
m.readability = Enums.random(Readability.class);
m.address = Enums.random(Address.class);
m.returnAddress = Enums.random(ReturnAddress.class);
عودة م؛
}
مولد Iterable<Mail> ثابت عام (عدد int النهائي) {
إرجاع Iterable جديد<Mail>() {
int n = العد؛
مكرر عام <Mail> مكرر () {
إرجاع مكرر جديد<Mail>() {
public boolean hasNext() { return n--> 0 }
البريد العام التالي () {إرجاع البريد العشوائي () }
إزالة الفراغ العام () {// لم يتم تنفيذه
رمي UnsupportedOperationException () الجديد ؛
}
};
}
};
}
}
مكتب بريد من الدرجة العامة {
تعداد MailHandler {
عام_التسليم {
مقبض منطقي (بريد م) {
التبديل (م.التسليم العام) {
حالة نعم:
طباعة ("استخدام التسليم العام لـ" + m)؛
عودة صحيحة؛
الافتراضي: إرجاع خطأ؛
}
}
},
MACHINE_SCAN {
مقبض منطقي (بريد م) {
التبديل (م.المسح الضوئي) {
الحالة UNSCANNABLE: إرجاع خطأ؛
تقصير:
التبديل (م. العنوان) {
حالة غير صحيحة: إرجاع خطأ؛
تقصير:
print("تسليم "+ m +" تلقائيًا");
عودة صحيحة؛
}
}
}
},
VISUAL_INSPECTION {
مقبض منطقي (بريد م) {
التبديل (م. قابلية القراءة) {
حالة غير قانونية: إرجاع خطأ؛
تقصير:
التبديل (م. العنوان) {
حالة غير صحيحة: إرجاع خطأ؛
تقصير:
print("تسليم " + m + " بشكل طبيعي");
عودة صحيحة؛
}
}
}
},
RETURN_TO_SENDER {
مقبض منطقي (بريد م) {
التبديل (م.returnAddress) {
حالة مفقودة: إرجاع خطأ؛
تقصير:
طباعة("إرجاع " + m + " إلى المرسل");
عودة صحيحة؛
}
}
};
مقبض منطقي مجردة (البريد م)؛
}
مقبض باطل ثابت (البريد م) {
لـ (معالج MailHandler: MailHandler.values())
إذا (معالج.مقبض (م))
يعود؛
طباعة (م + "حرف ميت")؛
}
public static void main(String[] args) {
لـ(بريد البريد : Mail.generator(10)) {
طباعة (mail.details ())؛
مقبض (بريد) ؛
مطبعة("*****")؛
}
}
} /* الإخراج:
البريد 0، التسليم العام: NO2، إمكانية مسح العنوان: UNSCANNABLE، إمكانية قراءة العنوان: YES3، عنوان العنوان: OK1، عنوان المرسل: OK1
تسليم البريد 0 بشكل طبيعي
*****
البريد 1، التسليم العام: NO5، إمكانية مسح العنوان: YES3، إمكانية قراءة العنوان: غير مقروء، عنوان العنوان: OK5، عنوان المرسل: OK1
تسليم البريد 1 تلقائيا
*****
البريد 2، التسليم العام: نعم، إمكانية مسح العنوان: نعم 3، إمكانية قراءة العنوان: نعم 1، عنوان العنوان: OK1، عنوان المرسل: OK5
استخدام التسليم العام للبريد 2
*****
البريد 3، التسليم العام: NO4، إمكانية مسح العنوان: YES3، إمكانية قراءة العنوان: YES1، عنوان العنوان: غير صحيح، عنوان المرسل: OK4
إعادة البريد 3 إلى المرسل
*****
البريد 4، التسليم العام: NO4، إمكانية مسح العنوان: غير قابلة للمسح، إمكانية قراءة العنوان: YES1، عنوان العنوان: غير صحيح، عنوان المرسل: OK2
إعادة البريد 4 إلى المرسل
*****
البريد 5، التسليم العام: NO3، إمكانية مسح العنوان: YES1، إمكانية قراءة العنوان: غير مقروء، عنوان العنوان: OK4، عنوان المرسل: OK2
تسليم البريد 5 تلقائيا
*****
البريد 6، التسليم العام: نعم، إمكانية مسح العنوان: نعم 4، إمكانية قراءة العنوان: غير مقروء، عنوان العنوان: OK4، عنوان المرسل: OK4
استخدام التسليم العام للبريد 6
*****
البريد 7، التسليم العام: نعم، إمكانية مسح العنوان: نعم 3، إمكانية قراءة العنوان: نعم 4، عنوان العنوان: OK2، عنوان المرسل: مفقود
استخدام التسليم العام للبريد 7
*****
البريد 8، التسليم العام: NO3، إمكانية مسح العنوان: YES1، إمكانية قراءة العنوان: YES3، عنوان العنوان: غير صحيح، عنوان المرسل: مفقود
البريد 8 هو حرف ميت
*****
البريد 9، التسليم العام: NO1، إمكانية مسح العنوان: UNSCANNABLE، إمكانية قراءة العنوان: YES2، عنوان العنوان: OK1، عنوان المرسل: OK4
تسليم البريد 9 بشكل طبيعي
*****
*///:~
يعد نوع التعداد أيضًا نوعًا مثاليًا لإنشاء آلة حالة. يمكن لآلة الحالة أن تنتقل بين عدد محدود من الحالات وفقًا للإدخال، ثم تنهي العمل بعد استيفاء حالة معينة. بالإضافة إلى ذلك، سيكون لكل حالة تعد آلة البيع مثالاً على آلة الحالة النموذجية حيث نحدد مدخلات مختلفة ضمن التعداد:
انسخ رمز الكود كما يلي:
//: تعداد/Input.java
الحزمة المذكورة؛
import java.util.*;
إدخال التعداد العام {
النيكل (5)، الدايم (10)، الربع (25)، الدولار (100)، معجون الأسنان (200)، رقائق البطاطس (75)، الصودا (100)، الصابون (50)، ABORT_TRANSACTION {
كمية كثافة العمليات العامة () {// عدم السماح
طرح RuntimeException الجديد ("ABORT.amount ()")؛
}
},
STOP {// يجب أن يكون هذا هو المثيل الأخير.
كمية كثافة العمليات العامة () {// عدم السماح
طرح RuntimeException الجديد("SHUT_DOWN.amount()");
}
};
قيمة int؛ // بالسنت
الإدخال (قيمة كثافة العمليات) { this.value = value }
مدخل() {}
int المبلغ () {قيمة الإرجاع }؛
راند عشوائي ثابت = عشوائي جديد (47)؛
الإدخال الثابت العام RandomSelection() {
// لا تقم بتضمين STOP:
قيم الإرجاع () [rand.nextInt (القيم (). الطول - 1)]؛
}
} ///:~
يتم استخدام VendingMachine للرد على الإدخال أولاً، حيث يقوم بتصنيف الإدخال من خلال تعداد الفئة، ثم يستخدم عبارة التبديل:
انسخ رمز الكود كما يلي:
//: تعداد/VendingMachine.java
// {الوسائط: VendingMachineInput.txt}
الحزمة المذكورة؛
import java.util.*;
import net.mindview.util.*;
import static enumerated.Input.*;
import static net.mindview.util.Print.*;
فئة التعداد {
MONEY(NICKEL، DIME، QUARTER، DOLLAR)،ITEM_SELECTION(معجون الأسنان، رقائق البطاطس، الصودا، الصابون)،QUIT_TRANSACTION(ABORT_TRANSACTION)،SHUT_DOWN(STOP)؛
قيم الإدخال الخاص[]؛
الفئة (الإدخال... الأنواع) { القيم = الأنواع }
فئات EnumMap ثابتة خاصة <Input,Category> = new EnumMap<Input,Category>(Input.class);
ثابت {
for(الفئة ج: Category.class.getEnumConstants())
لـ (نوع الإدخال: قيم c.)
Categories.put(type, c);
}
تصنيف الفئة الثابتة العامة (إدخال الإدخال) {
إرجاع الفئات.get(input);
}
}
الطبقة العامة VendingMachine {
حالة الحالة الثابتة الخاصة = State.RESTING؛
كمية كثافة العمليات الثابتة الخاصة = 0؛
تحديد الإدخال الثابت الخاص = فارغ؛
enum StateDuration {TRANSIENT} // وضع العلامات enum
حالة التعداد {
يستريح {
باطلة التالي (إدخال الإدخال) {
التبديل(Category.categorize(input)) {
حالة المال:
المبلغ += input.amount();
الحالة = ADDING_MONEY؛
استراحة؛
حالة SHUT_DOWN:
الحالة = المحطة الطرفية؛
تقصير:
}
}
},
إضافة_أموال {
باطلة التالي (إدخال الإدخال) {
التبديل(Category.categorize(input)) {
حالة المال:
المبلغ += input.amount();
استراحة؛
الحالة ITEM_SELECTION:
الاختيار = الإدخال؛
إذا (المبلغ <الاختيار.المبلغ ())
طباعة ("المال غير كافٍ لـ" + التحديد)؛
حالة أخرى = الاستغناء؛
استراحة؛
الحالة QUIT_TRANSACTION:
الحالة = GIVING_CHANGE؛
استراحة؛
حالة SHUT_DOWN:
الحالة = المحطة الطرفية؛
تقصير:
}
}
},
التوزيع (StateDuration.TRANSIENT) {
باطل التالي () {
طباعة ("هذا هو اختيارك" +)؛
المبلغ -= التحديد. المبلغ();
الحالة = GIVING_CHANGE؛
}
},
GIVING_CHANGE(StateDuration.TRANSIENT) {
باطل التالي () {
إذا (المبلغ > 0) {
طباعة ("التغيير الخاص بك:" + المبلغ)؛
المبلغ = 0؛
}
الحالة = الراحة؛
}
},
المحطة الطرفية {إخراج الفراغ () {طباعة ("توقف" } })؛
منطقية خاصة هي Transient = false؛
ولاية() {}
State(StateDuration trans) {isTransient = true }
باطلة التالي (إدخال الإدخال) {
throw new RuntimeException("اتصل فقط" + "التالي (إدخال الإدخال) للحالات غير العابرة");
}
باطل التالي () {
throw new RuntimeException("اتصل فقط بـ next() لحالات " + "StateDuration.TRANSIENT");
}
إخراج باطل () {طباعة (المبلغ) ؛
}
تشغيل الفراغ الثابت (Generator<Input> gen) {
بينما (الحالة!= الحالة.المحطة الطرفية) {
State.next(gen.next());
بينما (state.isTransient)
State.next();
State.output();
}
}
public static void main(String[] args) {
Generator<Input> gen = new RandomInputGenerator();
إذا (args. length == 1)
gen = new FileInputGenerator(args[0]);
تشغيل (الجنرال)؛
}
}
// للتحقق من سلامة العقل الأساسية:
فئة RandomInputGenerator تنفذ Generator<Input> {
الإدخال العام التالي () {return Input.randomSelection ()}؛
}
// إنشاء مدخلات من ملف مكون من سلاسل مفصولة بـ ';':
فئة FileInputGenerator تنفذ Generator<Input> {
إدخال التكرار الخاص <String> ؛
عام FileInputGenerator (اسم الملف سلسلة) {
input = new TextFile(fileName, ";").iterator();
}
الإدخال العام التالي () {
إذا (!input.hasNext())
عودة فارغة؛
return Enum.valueOf(Input.class, input.next().trim());
}
} /* الإخراج:
هنا رقائق الخاص بك
هنا معجون الأسنان الخاص بك
التغيير الخاص بك: 35
أموال غير كافية للصودا
أموال غير كافية للصودا
التغيير الخاص بك: 75
توقف
*///:~
فيما يلي بيانات الاختبار المستخدمة لإنشاء الإخراج أعلاه:
انسخ رمز الكود كما يلي:
ربع؛
دولار؛
ربع الدايم؛
ربع الدايم؛
ربع الدايم؛
ABORT_TRANSACTION؛
قف؛
///:~
التفريغ المتعدد عند التعامل مع التفاعلات بين أنواع متعددة، من المحتمل أن تصبح التعليمات البرمجية فوضوية، مثل Number.plush(Number)، Number.mutiply(Number)، وما إلى ذلك. الرقم هو مجرد فئة أساسية من العائلة، لذلك عند الاتصال عندما a.plus(b)، فأنت لا تعرف نوع a ولا نوع b، فكيف تتأكد من صحة التفاعل بينهما؟ يمكن لـ Java تنفيذ عملية تفريغ واحدة فقط، أي إذا تم تنفيذ عملية واحدة أو أكثر من أنواع متعددة غير معروفة، فيمكن لـ Java تنفيذ آلية ربط ديناميكية فقط على أحد الأنواع، وهذا لا يمكنه حل المشكلة التي تحدثنا عنها أعلاه لكتابة رمز الربط الديناميكي يدويًا.
الحل هو استخدام الربط المتعدد. يمكن أن يحدث تعدد الأشكال فقط عند استدعاء إحدى الطرق، لذلك إذا كنت بحاجة إلى تفريغ متعدد، فيجب عليك استدعاء طرق متعددة. مع إلغاء التغليف المتعدد، يجب أن يكون لديك أسلوب ظاهري يستدعي أسلوب كل نوع لإلغاء التغليف. المثال التالي هو مثال حجرة ورقة مقص:
انسخ رمز الكود كما يلي:
//: تعداد/Outcome.java
الحزمة المذكورة؛
التعداد العام النتيجة { فوز، خسارة، رسم } ///:~
//: تعداد/RoShamBo1.java
// عرض الإرسال المتعدد.
الحزمة المذكورة؛
import java.util.*;
import static enumerated.Outcome.*;
عنصر الواجهة {
تنافس النتيجة(البند عليه)؛
تقييم النتيجة (الورقة ع)؛
تقييم النتائج (مقص)؛
تقييم النتيجة (روك ص)؛
}
فئة الورق تنفذ العنصر {
النتيجة العامة تنافس (Item it) {return it.eval (this) ؛
تقييم النتيجة العامة (الورقة ع) {return DRAW}
تقييم النتيجة العامة (مقص) {return WIN}
تقييم النتيجة العامة (Rock r) {return LOSE}
سلسلة عامة toString () {إرجاع "الورق" }؛
}
فئة مقص تنفذ البند {
النتيجة العامة تنافس (Item it) {return it.eval (this) ؛
تقييم النتيجة العامة (الورقة ع) {return LOSE}
تقييم النتيجة العامة (مقص) {return DRAW}
تقييم النتيجة العامة (Rock r) {return WIN}
سلسلة عامة toString () {إرجاع "مقص" }؛
}
فئة روك تنفذ العنصر {
تتنافس النتيجة العامة (عنصر) {return It.eval (this) ؛
النتيجة العامة eval (paper p) {return win ؛
النتائج العامة eval (مقص S)
النتيجة العامة eval (Rock r) {return draw ؛
السلسلة العامة ToString () {Return "Rock" ؛
}
الطبقة العامة Roshambo1 {
ثابت ثابت في الحجم int = 20 ؛
راند العشوائية الثابتة الخاصة = عشوائي جديد (47) ؛
العنصر الثابت العام NewItem () {
التبديل (Rand.NextInt (3)) {
تقصير:
الحالة 0: إرجاع مقص جديد () ؛
الحالة 1: إرجاع ورقة جديدة () ؛
القضية 2: إرجاع New Rock () ؛
}
}
تطابق الفراغ الثابت العام (البند أ ، البند ب) {
System.out.println (A + "Vs." + B + ":" + A.Compete (B)) ؛
}
public static void main(String[] args) {
لـ (int i = 0 ؛ i <size ؛ i ++)
Match (NewItem () ، newItem ()) ؛
}
} /* الإخراج:
موسيقى الروك مقابل الصخرة: ارسم
الورق مقابل موسيقى الروك: فوز
الورق مقابل موسيقى الروك: فوز
الورق مقابل موسيقى الروك: فوز
مقص مقابل الورق: فوز
مقص مقابل مقص: ارسم
مقص مقابل الورق: فوز
موسيقى الروك مقابل الورق: خسارة
الورق مقابل الورق: ارسم
موسيقى الروك مقابل الورق: خسارة
الورق مقابل المقص: خسارة
الورق مقابل المقص: خسارة
موسيقى الروك مقابل المقص: فوز
موسيقى الروك مقابل الورق: خسارة
الورق مقابل موسيقى الروك: فوز
مقص مقابل الورق: فوز
الورق مقابل المقص: خسارة
الورق مقابل المقص: خسارة
الورق مقابل المقص: خسارة
الورق مقابل المقص: خسارة
*///: ~
استخدمنا العديد من الطرق لتحقيق تفريغ متعددة ، ولكن ما حصلنا عليه كان بنية رمز جيدة. المشكلة الأكبر عند استخدام حل التعداد لتنفيذ الكود أعلاه هي أن مثيل التعداد ليس نوعًا ، لذلك لا يمكن استخدام مثيل التعداد كنوع المعلمة. ولكن لا يزال بإمكاننا أن يكون لدينا طرق أخرى للتغلب على هذه العقبة.
انسخ رمز الكود كما يلي:
//: مُعداد/Roshambo2.java
// تبديل التعداد على آخر.
حزمة مخصصة.
استيراد static redumerated.outcome.*؛
التعداد العام Roshambo2 ينفذ منافس <roshambo2> {
الورق (السحب ، الخسارة ، الفوز) ، مقص (الفوز ، السحب ، الخسارة) ، روك (خسارة ، الفوز ، السحب) ؛
نتائج النتائج الخاصة ، Vscissors ، Vrock ؛
Roshambo2 (ورقة النتائج ، مقص النتائج ، صخرة النتيجة) {
this.vaper = paper ؛
this.vscissors = مقص ؛
this.vrock = الصخور ؛
}
تتنافس النتيجة العامة (Roshambo2 It) {
التبديل (it) {
تقصير:
ورقة الحالة: إرجاع Vappe ؛
مقص الحالات: إرجاع vscissors ؛
قضية الصخور: إرجاع Vrock ؛
}
}
public static void main(String[] args) {
Roshambo.play (Roshambo2.class ، 20) ؛
}
} /* الإخراج:
موسيقى الروك مقابل الصخرة: ارسم
مقص مقابل الصخور: خسارة
مقص مقابل الصخور: خسارة
الأنواع المذكورة 753
مقص مقابل الصخور: خسارة
الورق مقابل المقص: خسارة
الورق مقابل الورق: ارسم
الورق مقابل المقص: خسارة
موسيقى الروك مقابل المقص: فوز
مقص مقابل مقص: ارسم
موسيقى الروك مقابل المقص: فوز
مقص مقابل الورق: فوز
مقص مقابل الورق: فوز
موسيقى الروك مقابل الورق: خسارة
موسيقى الروك مقابل المقص: فوز
مقص مقابل الصخور: خسارة
الورق مقابل المقص: خسارة
مقص مقابل الورق: فوز
مقص مقابل الورق: فوز
مقص مقابل الورق: فوز
مقص مقابل الورق: فوز
*///: ~
انسخ رمز الكود كما يلي:
//: مُعداد/منافس
// تبديل التعداد على آخر.
حزمة مخصصة.
منافس الواجهة العامة <T يمتد منافس <T >> {
النتيجة المنافسة (T منافس) ؛
} ///: ~
انسخ رمز الكود كما يلي:
//: مُعداد/Roshambo.java
// أدوات شائعة لأمثلة Roshambo.
حزمة مخصصة.
استيراد net.mindview.util.*؛
الطبقة العامة Roshambo {
الثابت العام <t يمتد منافس <t >> void Match (t a ، t b) {
System.out.println (A + "Vs." + B + ":" + A.Compete (B)) ؛
}
الثابت العام <t يمتد التعداد <T> والمنافس <t >> play void (الفئة <T> rsbclass ، حجم int) {
لـ (int i = 0 ؛ i <size ؛ i ++)
Match (Enums.Random (RSBClass) ، Enums.Random (RSBClass)) ؛
}
} ///: ~
نظرًا لأن صياغة الأساليب الساكنة يمكن أن توفر طرقًا مختلفة لكل نوع تعداد ، يبدو أنه حل جيد لتحقيق تفريغ متعددة ، لكننا ما زلنا نواجه مشكلة أن مثيل التعداد ليس نوعًا ، لذلك كل ما يمكننا فعله هو إضافة عبارة تبديل :
انسخ رمز الكود كما يلي:
//: مُعداد/Roshambo3.java
// باستخدام طرق ثابتة محددة.
حزمة مخصصة.
استيراد static redumerated.outcome.*؛
التعداد العام Roshambo3 ينفذ منافس <roshambo3> {
ورق {
تتنافس النتيجة العامة (Roshambo3 It) {
التبديل (it) {
افتراضي: // لوضع المترجم
ورقة الحالة: رسم العودة ؛
مقص القضية: عودة خسارة ؛
قضية موسيقى الروك: فوز العودة ؛
}
}
} ،
مقص {
تتنافس النتيجة العامة (Roshambo3 It) {
التبديل (it) {
تقصير:
ورقة الحالة: عودة الفوز ؛
مقص القضية: سحب العودة ؛
قضية الصخرة: عودة تخسر ؛
}
}
} ،
صخر {
تتنافس النتيجة العامة (Roshambo3 It) {
التبديل (it) {
تقصير:
ورقة الحالة: عودة خسارة ؛
مقص القضية: عودة الفوز ؛
قضية الصخور: سحب العودة ؛
}
}
};
النتيجة التجريدية العامة تتنافس (Roshambo3 IT) ؛
public static void main(String[] args) {
Roshambo.play (Roshambo3.class ، 20) ؛
}
}/ * نفس الإخراج مثل Roshambo2.java * ///: ~
الكود التالي هو طريقة تنفيذ أكثر إيجازا:
انسخ رمز الكود كما يلي:
//: مُعداد/Roshambo4.java
حزمة مخصصة.
التعداد العام Roshambo4 ينفذ منافس <roshambo4> {
صخر {
تتنافس النتيجة العامة (خصم Roshambo4) {
العائد منافسة (مقص ، خصم) ؛
}
} ،
مقص {
تتنافس النتيجة العامة (خصم Roshambo4) {
إرجاع المنافسة (ورقة ، خصم) ؛
}
} ،
ورق {
تتنافس النتيجة العامة (خصم Roshambo4) {
العودة منافسة (الصخور ، الخصم) ؛
}
};
تنافس النتيجة (Roshambo4 Soer ، Roshambo4 خصم) {
العودة ((الخصم == this)؟ stite.draw: ((الخصم == خاسر)؟ النتيجة.
}
public static void main(String[] args) {
Roshambo.play (Roshambo4.class ، 20) ؛
}
}/ * نفس الإخراج مثل Roshambo2.java * ///: ~
يبدو أن فئة Enummap هي وسيلة جيدة لتنفيذ تفريغ متعددة في الواقع:
انسخ رمز الكود كما يلي:
//: مُعداد/Roshambo5.java
// الإرسال المتعدد باستخدام enummap من enummaps.
حزمة مخصصة.
import java.util.*;
استيراد static redumerated.outcome.*؛
Enum Roshambo5 ينفذ منافس <roshambo5> {
ورقة ، مقص ، صخرة ؛
static enummap <Roshambo5 ، enummap <Roshambo5 ، النتائج >> TABLE = NEW ENUMMAP <ROSHAMBO5 ، ENUMMAP <ROSHAMBO5 ، النتيجة >> (Roshambo5.class) ؛
ثابت {
لـ (Roshambo5 IT: Roshambo5.values ())
Table.put (It ، New Enummap <Roshambo5 ، neptred> (Roshambo5.class)) ؛
initRow (ورقة ، رسم ، خسارة ، الفوز) ؛
initRow (مقص ، Win ، Draw ، خسارة) ؛
initRow (Rock ، Lose ، Win ، Draw) ؛
}
it static void initrow (roshambo5 It ، Vapter ، نتائج Vscissors ، نتائج Vrock) {
enummap <Roshambo5 ، stept> row = roshambo5.table.get (it) ؛
row.put (Roshambo5.paper ، Vappe) ؛
row.put (Roshambo5.scissors ، vscissors) ؛
row.put (Roshambo5.rock ، vrock) ؛
}
تتنافس النتيجة العامة (Roshambo5 it) {
إرجاع جدول.
}
public static void main(String[] args) {
Roshambo.play (Roshambo5.class ، 20) ؛
}
}/ * نفس الإخراج مثل Roshambo2.java * ///: ~
يمكننا أيضًا استخدام ميزة التعداد مع قيم ثابتة لاستخدام البيانات لأبسط طريقة التنفيذ.
انسخ رمز الكود كما يلي:
//: مُعداد/Roshambo6.java
// التعداد باستخدام "الجداول" بدلاً من الإرسال المتعدد.
حزمة مخصصة.
استيراد static redumerated.outcome.*؛
ENUM ROSHAMBO6 ينفذ منافس <roshambo6> {
ورقة ، مقص ، صخرة ؛
النتيجة الثابتة الخاصة [] [] جدول = {
{Draw ، Lost ، Win} ، // paper
{فوز ، ارسم ، خسارة} ، // مقص
{Lose ، Win ، Draw} ، // Rock
};
تتنافس النتيجة العامة (Roshambo6 Other) {
جدول الإرجاع [this.ordinal ()] [other.ordinal ()] ؛
}
public static void main(String[] args) {
Roshambo.play (Roshambo6.class ، 20) ؛
}
} ///: ~