2013-07-23 28 views
5

Có thể bằng cách nào đó đánh dấu một số giá trị nhất định trong Java là gói riêng tư, tức là cung cấp cho chúng công cụ sửa đổi mặc định không?Mức độ hiển thị của các giá trị enum trong Java

nền (chỉ để chặn trước những nhận xét đầu tiên khác ngay lập tức "Để làm gì?";))

Tôi có một -object Task với thực-phương pháp khác nhau và thực hiện-trạng thái đó quyết định những phương pháp để gọi kế tiếp. Mỗi một phương thức thực thi trả về trạng thái thực hiện của phương thức tiếp theo được gọi (về cơ bản là một khung công tác để thực hiện một máy trạng thái).

Tôi có enum chứa tất cả các trạng thái thực thi có thể, nhưng cũng chứa một vài trạng thái "gói nội bộ" như "đang chờ xử lý" hoặc "không thành công" mà không thể trả lại bằng phương thức thực thi.

Tôi biết mình có thể quản lý các trạng thái này trong một biến riêng biệt với enum riêng của nó, nhưng điều đó sẽ làm cho mã kém sạch hơn nhiều khi nó biến một đơn vị thành switch thành (ít nhất) hai (và có thể là if xung quanh)). Ngoài ra, tôi có thể, tất nhiên, chỉ cần kiểm tra giá trị trả lại, nhưng tôi thậm chí không muốn làm cho những cái sai có sẵn ở nơi đầu tiên.

+3

Không, bạn không thể đánh dấu một số hằng số enum công khai và một số gói riêng tư. –

+1

Trong trường hợp này có thể bạn có thể sử dụng các enums java cũ, chỉ là một lớp với một số hằng số tĩnh cuối cùng. – Marcelo

+0

Trong thực tế, bạn không thể đánh dấu chúng bất cứ điều gì. Họ là 'công khai' và đó là nó. –

Trả lời

5

Có vẻ như câu trả lời đơn giản là "Không."

Nhưng, suy nghĩ về những ý kiến ​​khác nhau và câu trả lời (đặc biệt là bởi Marcelo, BlackVegetable và OldCurmudgeon), tôi đã đưa ra những cách giải quyết như sau:

Một gói tin enum chứa tất cả các giá trị:

enum PackagePrivateEnum { 
    PUBLIC_VALUE_1, 
    PUBLIC_VALUE_2, 
    PUBLIC_VALUE_3, 
    PACKAGE_PRIVATE_VALUE_1, 
    PACKAGE_PRIVATE_VALUE_2; 
} 

Một thứ hai công enum chỉ chứa các giá trị cộng đồng, và trực tiếp bản đồ này để những gói tin:

public enum PublicEnum { 
    PUBLIC_VALUE_1 (PackagePrivateEnum.PUBLIC_VALUE_1), 
    PUBLIC_VALUE_2 (PackagePrivateEnum.PUBLIC_VALUE_2), 
    PUBLIC_VALUE_3 (PackagePrivateEnum.PUBLIC_VALUE_3); 

    final PackagePrivateEnum value; 

    private PublicEnum(PackagePrivateEnum value) { 
     this.value = value; 
    } 
} 

Bây giờ, nếu tôi có một chức năng mà chỉ được phép quay trở lại một trong những giá trị nào, tôi định nghĩa nó như:

public abstract PublicEnum returnSomething(); 

và sau đó có thể sử dụng nó trong gói qua:

PackagePrivateEnum value = returnSomething().value; 

Điều này ẩn các giá trị không mong muốn của công chúng và, tôi tin rằng, đồng thời giảm thiểu chi phí mã hóa và hiệu suất bên trong gói (ví dụ: không có chuyển đổi hoặc báo cáo nếu không có bản đồ tra cứu, vv, chỉ cần yêu cầu .value). Trong thực tế, với một trình biên dịch thông minh như GWT, giá trị trả về có lẽ sẽ nhận được "nội tuyến" đến mức ngay cả khi .value -lookup bị xóa hoàn toàn, tức là không có chi phí hiệu năng nào cả. Ngoài ra, với điều này, có thể xác định một số tùy ý các tập con được phép khác nhau của một enum tập thể lớn cho các ngữ cảnh khác nhau: Tôi có thể dễ dàng xác định một số PublicEnum2 khác để hiển thị một tập hợp giá trị hoàn toàn khác từ PackagePrivateEnum.

+0

Câu trả lời này là những gì tôi đang nhắm đến trong bình luận của tôi. +1 – BlackVegetable

+0

@BlackVegetable :) Bây giờ nó có ý nghĩa! Tôi đã thêm bạn vào danh sách trên cùng ... :) –

1

Bạn gặp khó khăn vì bạn đang sử dụng mẫu sai.

Task s không được trả về trạng thái tiếp theo. Bạn nên sử dụng ma trận State để kiểm soát luồng. Bằng cách này, luồng của bạn không bị rối loạn bên trong các nhiệm vụ và các State s vẫn còn riêng tư cho hệ thống luồng.

Nếu bạn muốn Task để kiểm soát luồng, chúng sẽ trả lại thứ gì đó (có thể thành công/thất bại) để tác động đến bộ điều khiển luồng. Họ không được xác định trạng thái tiếp theo, họ phải ảnh hưởng đến trạng thái tiếp theo.

Added

Dưới đây là một ví dụ hơi giả tạo của những gì tôi có ý nghĩa. Chú ý cách Task s được gắn vào mỗi State và luồng được điều khiển bởi một Map chỉ đơn thuần giữ mỗi chuyển đổi trạng thái.

Tôi đã thực hiện một nỗ lực mã thông báo để phù hợp với kết quả trả về của bạn, nhưng tôi nghi ngờ rằng chỉ cần làm quá tải các vấn đề và một khi bạn nắm lấy sự tách biệt dòng chảy, bạn sẽ nhận ra những gì tôi đang cố giải thích.

public class Test { 
    public void test() { 
    new Thread(new Engine()).start(); 
    } 

    static final Map<State, State> flow = new HashMap<>(); 

    static { 
    flow.put(State.Start, State.A); 
    flow.put(State.A, State.B); 
    flow.put(State.B, State.Finished); 
    } 

    public static class Engine implements Runnable { 
    State state = State.Start; 

    @Override 
    public void run() { 
     while (state != State.Finished) { 
     System.out.println("State: "+state); 
     // Perform all tasks of this state. 
     for (Task task : state.tasks) { 
      System.out.println("Task: "+task); 
      Result result = Result.Start; 
      // Keep performing until completed. 
      while (result != Result.Completed) { 
      System.out.println("Result: "+result); 
      result = result.perform(task); 
      } 
      System.out.println("Result: "+result); 
     } 
     // All tasks performed! Next state. 
     state = flow.get(state); 
     } 
     System.out.println("State: "+state); 
    } 
    } 

    enum State { 
    Start, 
    A(Task.One, Task.Two), 
    B(Task.Two), 
    Finished; 
    Iterable<Task> tasks; 

    State(Task... tasks) { 
     this.tasks = Arrays.asList(tasks); 
    } 
    } 

    enum Result { 
    Start { 
     @Override 
     Result perform(Task t) { 
     return t.initialise(); 
     } 
    }, 
    Executing { 
     @Override 
     Result perform(Task t) { 
     return t.execute(); 
     } 
    }, 
    Finalising { 
     @Override 
     Result perform(Task t) { 
     return t.finalise(); 
     } 
    }, 
    Completed { 
     @Override 
     Result perform(Task t) { 
     // Stop there. 
     return Completed; 
     } 
    }; 

    abstract Result perform(Task t); 
    } 

    enum Task { 
    One { 
     @Override 
     Result initialise() { 
     return Result.Executing; 
     } 

     @Override 
     Result execute() { 
     return Result.Finalising; 
     } 

     @Override 
     Result finalise() { 
     return Result.Completed; 
     } 
    }, 
    Two { 
     @Override 
     Result initialise() { 
     return Result.Executing; 
     } 

     @Override 
     Result execute() { 
     return Result.Finalising; 
     } 

     @Override 
     Result finalise() { 
     return Result.Completed; 
     } 
    }; 

    abstract Result initialise(); 

    abstract Result execute(); 

    abstract Result finalise(); 
    } 

    public static void main(String args[]) { 
    try { 
     new Test().test(); 
    } catch (Throwable t) { 
     t.printStackTrace(System.err); 
    } 
    } 
} 

Added

Đơn giản hóa này bằng cách loại bỏ yêu cầu của bạn để kiểm soát dòng chảy thông qua các kết quả của các phương pháp nhiệm vụ chúng tôi nhận:

public class Test { 
    public void test() { 
    new Thread(new Engine()).start(); 
    } 

    static final Map<State, State> flow = new HashMap<>(); 

    static { 
    flow.put(State.Start, State.A); 
    flow.put(State.A, State.B); 
    flow.put(State.B, State.Finished); 
    } 

    public static class Engine implements Runnable { 
    State state = State.Start; 

    @Override 
    public void run() { 
     while (state != State.Finished) { 
     System.out.println("State: "+state); 
     // Perform all tasks of this state. 
     for (Task task : state.tasks) { 
      System.out.println("Task: "+task); 
      task.initialise(); 
      task.execute(); 
      task.finalise(); 
     } 
     // All tasks performed! Next state. 
     state = flow.get(state); 
     } 
     System.out.println("State: "+state); 
    } 
    } 

    enum State { 
    Start, 
    A(Task.One, Task.Two), 
    B(Task.Two), 
    Finished; 
    Iterable<Task> tasks; 

    State(Task... tasks) { 
     this.tasks = Arrays.asList(tasks); 
    } 
    } 

    enum Task { 
    One { 
     @Override 
     void execute() { 
     } 
    }, 
    Two { 
     @Override 
     void execute() { 
     } 
    }; 

    // Nothing by default. 
    void initialise() { 
    } 

    abstract void execute(); 

    // Nothing by default. 
    void finalise() { 
    } 

    } 

    public static void main(String args[]) { 
    try { 
     new Test().test(); 
    } catch (Throwable t) { 
     t.printStackTrace(System.err); 
    } 
    } 
} 

đó, tôi nghĩ rằng, chứng tỏ việc tách kiểm soát dòng chảy từ thực hiện nhiệm vụ mà tôi đã cố gắng vượt qua.

+0

Về cơ bản, 'Task' của tôi có một khởi tạo-, một thực thi và một phương thức hoàn thiện. Các phương thức khởi tạo và thực thi trả về một trạng thái EXECUTING, WAITING, FINALIZING hoặc COMPLETED, sẽ gây ra execute() được gọi tiếp theo, nhiệm vụ được đặt ở trạng thái giữ, finalize() được gọi là next, hoặc nhiệm vụ được đánh dấu hoàn thành tương ứng. Nó thực sự là giải pháp tốt nhất ở đây để xác định một enum thứ hai với 4 giá trị trả về có thể và xử lý rằng với một tuyên bố chuyển đổi chỉ để làm "nếu WAITING, state = WAITING; nếu COMPLETED, state = COMPLETED; ..." chất thải ... –

+0

@MarkusA. - Tôi đã đăng một số mã - có lẽ điều đó sẽ giúp chứng minh điều tôi muốn nói. – OldCurmudgeon

+0

Có một số ý tưởng thực sự thú vị trong mã này! Cảm ơn! Ý tưởng thú vị để xác định phương thức "thực hiện" trực tiếp trên trạng thái enum và có nhiệm vụ là enum-value chứ không phải là các lớp. Ngoài ra, tôi không có ý tưởng rằng, trong một enum, bạn có thể định nghĩa một lớp trừu tượng và thực hiện nó trong một lần chụp. Hấp dẫn.Nhưng có vẻ như có rất nhiều sự vô cảm và nhìn lên trong mã của bạn và nó khá dài. Nhưng nó chắc chắn hữu ích để xem. +1 –

Các vấn đề liên quan