Внутренний класс.Какова его цель? - PullRequest
5 голосов
/ 03 августа 2010

Может кто-нибудь сказать мне, какова цель проведения внутренних классов? Я могу думать о некоторых, но, возможно, они не являются вескими причинами для использования внутренних классов. Я считаю, что внутренний класс полезен, когда вы хотите использовать класс, который не могут использовать другие классы. Что еще?

Ответы [ 5 ]

3 голосов
/ 03 августа 2010

Когда я изучал Java, мы использовали внутренние классы для классов обработки событий GUI.Это своего рода класс «одноразового использования», который не обязательно должен быть доступен другим классам, и относится только к классу, в котором он находится.

2 голосов
/ 03 августа 2010

Внутренние классы могут использоваться для имитации замыканий: http://en.wikipedia.org/wiki/Closure_(computer_science)#Java

2 голосов
/ 03 августа 2010

Я использую внутренние классы для определения структуры, которая лучше всего представлена ​​содержащим классом, но не обязательно имеет смысл использовать отдельный внешний класс для представления структуры.

Чтобы привести пример, у меня есть класс, представляющий определенный тип сетевого устройства, и класс имеет определенные типы тестов, которые можно запускать на этом устройстве. Для каждого теста также существует потенциальный набор ошибок, которые можно найти. Каждый тип устройства может иметь различную структуру для ошибок.

С этим вы могли бы делать такие вещи, как

List<Error> errors = RemoteDeviceA.getErrors();

С методами, доступными из внутреннего класса, например

   for ( Error error : errors ) {
        System.out.println("MOnitor Type: " + error.getMonType());
        ...
   }

Конечно, есть и другие способы сделать это, это только внутриклассовый подход.

Упрощенный (он же неполный) код выше:

public class RemoteDeviceA {

    private String host;
    private String user;
    private String password;
    private static List<Error> errors;

    public RemoteDeviceA(String user, String host, String password) {
        this.host = host;
        this.user = user;
        this.password = password;

        login();
    }

    private void login() {
        // Logs in
    }

    public void runTestA() {

        List<Error> errorList = new ArrayList<Error>();

        //loop through test results

        if (!value.equals("0")) {
            Error error = new Error(node, rackNum, shelfNum, slotNum, monType, value);
            if (error.isError()) {
                errorList.add(error);
            }
        }
        setErrors(errorList);
    }

    private static void setErrors(List<Error> errors) {
        RemoteDeviceA.errors = errors;
    }

    public List<Error> getErrors() {
        return errors;
    }

    public class Error {

        private String monType;
        private String node;
        private String rack;
        private String shelf;
        private String slot;
        private String value;
        private boolean error = false;
        private boolean historyError = false;
        private boolean critical = false;
        private boolean criticalHistory = false;

        Error(String node, String rack, String shelf, String slot,
                String monType, String value) {
            parseAlarm(node, rack, shelf, slot, monType, value);
        }

        private void parseAlarm(String node, String rack, String shelf,
                String slot, String monType, String value) {

            String modType = "";

            if (monType.startsWith("ES_15") && !value.equals("0")) {
                setMonType("ES_15");
                setError(true);
            } else if (monType.startsWith("SES_15") && !value.equals("0")) {
                setMonType("SES_15");
                setError(true);
            } else if (monType.startsWith("BBE_15") && !value.equals("0")) {
                setMonType("BBE_15");
                setError(true);
            } else if (monType.startsWith("UT_15") && !value.equals("0")) {
                setMonType("UT_15");
                setError(true);
                setCritial(critical);
            } else if (monType.startsWith("ES_24") && !value.equals("0")) {
                setMonType("ES_24");
                setHistoryError(true);
                setError(true);
            } else if (monType.startsWith("SES_24") && !value.equals("0")) {
                setMonType("SES_24");
                setHistoryError(true);
                setError(true);
            } else if (monType.startsWith("BBE_24") && !value.equals("0")) {
                setMonType("BBE_24");
                setHistoryError(true);
                setError(true);
            } else if (monType.startsWith("UT_24") && !value.equals("0")) {
                setMonType("UT_24");
                setHistoryError(true);
                setError(true);
                setCriticalHistory(true);
            } else if (monType.startsWith("UT_15") && !value.equals("0")) {
                setMonType("UT_15");
                setError(true);
                setCritial(true);
            } else if (monType.startsWith("LASPWR")) {

                float laserPwr = Float.valueOf(value);

                if (node.startsWith("LEM_EM")) {
                    if ((laserPwr < 8.0) || (laserPwr > 12.0)) {
                        setMonType("LASERPWR");
                        setError(true);
                    }
                } else if (node.startsWith("LEM10")) {
                    if ((laserPwr < 18.0) || (laserPwr > 22.0)) {
                        setMonType("LASERPWR");
                        setError(true);
                    }
                }
            }

            if (isError()) {
                setNode(node);
                setRack(rack);
                setShelf(shelf);
                setSlot(slot);
                setValue(value);
                setError(true);
            }
        }

        private void setMonType(String monType) {
            this.monType = monType;
        }

        public String getMonType() {
            return monType;
        }

        private void setNode(String node) {
            this.node = node;
        }

        public String getNode() {
            return node;
        }

        public void setRack(String rack) {
            this.rack = rack;
        }

        public String getRack() {
            return rack;
        }

        public void setShelf(String shelf) {
            this.shelf = shelf;
        }

        public String getShelf() {
            return shelf;
        }

        public void setSlot(String slot) {
            this.slot = slot;
        }

        public String getSlot() {
            return slot;
        }

        private void setValue(String value) {
            this.value = value;
        }

        public String getValue() {
            return value;
        }

        private void setError(boolean error) {
            this.error = error;
        }

        public boolean isError() {
            return error;
        }  

        public void setCritial(boolean critical) {
            this.critical = critical;
        }   

        public boolean isCritical() {
            return critical;
        }   

        public void setCriticalHistory(boolean criticalHistory) {
            this.criticalHistory = criticalHistory;
        }  

        public boolean isCriticalHistory() {
            return criticalHistory;
        }  

        public void setHistoryError(boolean historyError) {
            this.historyError = historyError;
        }

        public boolean isHistoryError() {
            return historyError;
        }
    }
}
1 голос
/ 03 августа 2010

Я использую внутренние классы (в C ++) в ситуациях, когда несколько классов, не связанных с наследованием, имеют концептуально схожие детали реализации, которые образуют неявную часть открытого интерфейса и должны иметь одинаковые имена.

class lib::Identifier { ... };

class lib::Person {
public:
    class Identifier : public lib::Identifier { ... };
};

class lib::File {
public:
    class Identifier : public lib::Identifier { ... };
};

Это удобно для обозначения Identifier, Person::Identifier и File::Identifier как просто Identifier в соответствующих областях.

1 голос
/ 03 августа 2010

Реализация списка, которая внутренне использует связанный список для хранения элементов, может эффективно использовать внутренний класс для представления узлов в списке.Я думаю, что вы ударили по гвоздю, сказав, что вы будете использовать такой класс, в котором вы хотите использовать его внутренне для класса, но не хотите, чтобы он был открыт - класс «один раз», который действительно очень полезен'здесь'.

...