2017-01-27 9 views
5

मेरे पास एक समूह प्रोजेक्ट है जहां हमें प्रदान किए गए इंटरफेस और गणनाओं का उपयोग करने के लिए मजबूर किया जाता है।एनम पर जावा स्विच जो समान इंटरफ़ेस लागू करता है

नीचे की तरह एक स्थिति की कल्पना कीजिए:

// marker interface 
interface Request<T extends Response>{} 

// marker interface 
interface Response{} 

enum TypeAction implements Request<SomeEnumClassThatImplementsResponse>{ 
     TYPE1, TYPE2, TYPE3 
} 

enum OtherTypeAction implements Request<SomeOtherEnumClassThatImplementsResponse>{ 
     OTHERTYPE1, OTHERTYPE2  
} 

एक अन्य कक्षा में, मैं इस तरह का अनुरोध की एक सूची है: List<Request> req = new LinkedList<Request>() मुझे क्या करना चाहते हैं: बनाने के नीचे की तरह एक स्विच:

switch(a_request){ 
    CASE TYPE1: .... 
    CASE TYPE2: .... 
    CASE TYPE3: .... 
    CASE TYPE2: .... 
    CASE OTHERTYPE1: .... 
    CASE OTHERTYPE2: .... 
} 

मैं इसे कैसे प्रबंधित कर सकता हूं?

महत्वपूर्ण नोट: मैं इंटरफेस और enums में विधियों को जोड़ नहीं सकता लेकिन मैं नए enums बना सकता हूं जो ऊपर देख सकते हैं कि इंटरफेस लागू करता है। मेरे पास दो enums नहीं होगा जो संभव हो तो वही काम करते हैं।

संपादित करें: यह संभव डुप्लिकेट उत्तर से अलग है कि मैं अनुरोध इंटरफ़ेस में कोई भी विधि नहीं जोड़ सकता और इसलिए मैं enum कक्षाओं में एक विधि को लागू नहीं कर सकता।

, आप अपने वास्तविक कोड के लिए switch उपयोग नहीं कर सकते, लेकिन आप इस का उपयोग कर if बयान कर सकते हैं पहले से

+1

असल में, आप नहीं कर सकते। बस इसके बजाय 'if' का उपयोग करें। – shmosel

+3

जावा में विभिन्न enum कक्षाओं के संयुक्त के लिए स्विच स्टेटमेंट का संभावित डुप्लिकेट] (http://stackoverflow.com/questions/13958754/switch-statement-for-a-joint-of- अलग-enum-classes-in- जावा) – shmosel

+1

@ माइकलकुरी आप कैसे एक enum "कार्यान्वित" करते हैं? आप केवल इंटरफेस को लागू कर सकते हैं। – glglgl

उत्तर

4

आपके द्वारा उल्लेख किया जाने वाला स्विच स्पष्ट रूप से काम नहीं करता है।

मैं एक (काफी अजीब) प्रतिस्थापन:

private enum HelperEnum { 
     TYPE1(TypeAction.TYPE1), 
     TYPE2(TypeAction.TYPE2), 
     TYPE3(TypeAction.TYPE3), 
     OTHERTYPE1(OtherTypeAction.OTHERTYPE1), 
     OTHERTYPE2(OtherTypeAction.OTHERTYPE2), 

     private Request<T extends Response> source; 

     private HelperEnum(Request<T extends Response> source) { 
      this.source = source; 
     } 

     private static Map<Request<T extends Response>, HelperEnum> map; 

     public static HelperEnum lookUp(Request<SomeEnumClassThatImplementsResponse> source) { 
      if (map == null) { 
       map = Arrays.stream(HelperEnum.values()) 
        .collect(Collectors.toMap(x -> x.source, x -> x)); 
      } 
      return map.get(source); 
     } 

(अपरीक्षित विशेष रूप से स्थानों पर जहां मैं Request<T extends Response> का उपयोग करें: इस तरह एक "सहायक enum" जो सूचीबद्ध सभी मान हैं बनाते हैं, और एक Map<Request<Request<T extends Response>>, HelperEnum> है, गलत हो सकता है;।। मैं उन्हें पहले परीक्षण करने के लिए होगा लेकिन क्या आप अंदाजा हो जाना चाहिए)

इस तरह आप तो कर सकते हैं

switch(HelperEnum.lookUp(a_request)){ 
    case TYPE1: .... 
    case TYPE2: .... 
    case TYPE3: .... 
    case OTHERTYPE1: .... 
    case OTHERTYPE2: .... 
} 
+1

अच्छा विचार। बस एक टिप्पणी: ओपी के दो अलग-अलग enums हैं। तो उसे 'SomeEnumClassThatImplementsResponse' का उपयोग नहीं करना चाहिए, लेकिन enums के आम पूर्वज: 'अनुरोध <टी प्रतिक्रिया बढ़ाता है>' – davidxxx

+0

@davidxxx यह इंगित करने के लिए धन्यवाद। मैंने इसे बदल दिया – glglgl

1

दुर्भाग्य से धन्यवाद:

final List<Request> req = new LinkedList<>(); 

for (Request request : req) { 
    if (TypeAction.TYPE1.equals(request)) { 
     //code 
    } 
    else if (OtherTypeAction.OTHERTYPE1.equals(request)) { 
     //code 
    } 
} 

शायद तुम अनुरोध करने के लिए अधिक क्षेत्र में जोड़ सकते हैं और enums , और फिर आप इस दायर के बराबर कर सकते हैं।

4

आप इस्तेमाल कर सकते हैं एक स्विच के बजाय एक नक्शा:

interface MyRequestTypeAction{ 
    void doSomething(); 
} 

Map<Request, MyRequestTypeAction> requestActions = new HashMap<>(){{ 
    put(TypeAction.TYPE1,()->System.out.printLine("TypeAction.TYPE1")); 
    put(TypeAction.TYPE2,()->System.out.printLine("TypeAction.TYPE2")); 
    put(TypeAction.TYPE3,()->System.out.printLine("TypeAction.TYPE3")); 
    put(OtherTypeAction.OTHERTYPE1,()->System.out.printLine("OtherTypeAction.OTHERTYPE1")); 
    put(OtherTypeAction.OTHERTYPE2,()->System.out.printLine("OtherTypeAction.OTHERTYPE2")); 
}} 

requestActions.get(a_request).doSomething(); 
1

यदि आपके पास कोई व्यवहार है, जहां उदा। एक Request कई enumerated कार्यों को चालू कर सकते हैं, या व्यक्तिगत कार्यों 'कार्यान्वयन अन्य कार्यों से काफी अलग हैं, तो आप एक और अधिक लचीला समाधान की जरूरत है, तो आप उस तरह से जा सकते हैं:

public enum RequestHandlers { 
    TYPE1_HANDLER(TypeAction.TYPE1::equals, Request::methodA), 
    TYPE2_HANDLER(r -> r == TypeAction.TYPE2), 
    OTHERTYPE1_HANDLER(OtherTypeAction.OTHERTYPE1::equals), 
    COMMON_HANDLER(x -> true, MyLogger::trace); 

    private final Predicate<Request<?>> requestFilter; // selects supported requests for this handler 

    private final Consumer<Request<?>> consumer; // implements this handler's behaviour 

    private RequestHandlers(Predicate<Request<?>> p, Consumer<Request<?>> consumer) { 
     this.requestFilter = p; 
     this.consumer = consumer; 
    } 

    private RequestHandlers(Predicate<Request<?>> p) { 
     this.requestFilter = p; 
     this.consumer = Request::methodB; // default behaviour for all handlers 
    } 

    public static void handle(Request<?>... requests) { 
     Arrays.stream(RequestHandlers.values()) 
       .forEach(handler -> Arrays.stream(requests) 
             .filter(handler.requestFilter) 
             .forEach(request -> handler.consumer.accept(request))); 
    } 
} 

ध्यान दें कि मापदंड, जब कार्रवाई एक फिट बैठता है दिया गया अनुरोध, फ़िल्टर Predicate और Consumer द्वारा क्रिया द्वारा कॉन्फ़िगर करने योग्य है।

संबंधित मुद्दे