Подтвердить что ты не робот

Должен ли сбор констант помещаться в класс или интерфейс?

Если у меня есть набор статических констант, которые я хочу объявить централизованно, чтобы их можно было разделить между различными проектами, они должны быть помещены в класс или интерфейс (Java).

В прошлом я видел, что они в основном помещались в класс, но я начал думать, что, поскольку класс не будет и не должен быть создан, возможно, они будут лучше в интерфейсе, но затем интерфейс не должен реализовываться ни одним классы, например

public class ErrorCodes {
    public static final String ERROR_1 = "-1";
    public static final String ERROR_2 = "-2";
}

или

public interface ErrorCodes {
    public static final String ERROR_1 = "-1";
    public static final String ERROR_2 = "-2";
}
4b9b3361

Ответ 1

Если у них сильные соединения, я бы поместил их в перечисление:

public enum Error {
  ERROR_1("-1", "foo went wrong"),
  ERROR_2("-2", "bar went wrong");

  private final String id;
  private final String message;

  Error(String id, String message) {
    this.id=id;
    this.message=message;
  }

  public String getId() {
    return id;
  }

  public String getMessage() {
    return message;
  }
}

Преимущество состоит в том, что вы можете иметь безопасность типа в своем коде и что вы можете легко добавить поиск на основе идентификатора (либо построив HashMap<String,Error> в конструкторе, либо просто перейдя через values()).

Ответ 3

Здесь следует учитывать использование статического импорта (для импорта констант, определенных в классе), или безопасное имя.

От Интерфейс для констант

Размещение констант в интерфейсе было популярным методом в первые дни Java, но теперь многие считают его неприятным использованием интерфейсов, поскольку интерфейсы должны иметь дело с услугами, предоставляемыми объектом, а не его данными.
Кроме того, константы, используемые классом, обычно являются деталями реализации, но размещение их в интерфейсе продвигает их в общедоступный API класса.

Ответ 4

Это обсуждалось до:

Причина, по которой вам не нужны константы в интерфейсе, заключается в том, что она побуждает клиентские классы "реализовывать" этот интерфейс (чтобы получить доступ к константам без префикса их с именем интерфейса). Однако вы не должны - интерфейс фактически не является интерфейсом для возможностей объекта, а удобством компиляции, укоренившимся в внешнем типе класса.

Было время, когда "постоянный интерфейс" был очень удобен, но он всегда был "неправильным", и даже не лень является оправданием использовать его сейчас, когда мы имеем import static.

Изменить: Хотя я должен согласиться с тем, что для сценария, представленного в вашем вопросе, перечисления более подходят.

Ответ 5

Вы должны сделать это в классе.

Интерфейс - это описание доступных методов, свойств и т.д., к которым пользователи класса могут обращаться - посредством реализации интерфейса вы гарантируете, что члены, объявленные в интерфейсе, доступны пользователю.

С другой стороны, класс представляет собой описание объекта или (если вы не слишком сильно относитесь к принципам OO...), то местозаполнитель для статических членов. Я лично считаю, что в некоторых проектах очень полезно хранить кучу констант в классе Settings, поэтому мне не нужно оглядываться во всем проекте для определений. Я думаю, что этот подход - это то, за чем ты тоже.

Ответ 6

Вы должны поместить их в класс с помощью частного конструктора.

public class ErrorCodes {
    private ErrorCodes() {} // prevents instantiation
    public static final String ERROR_1 = "-1";
    public static final String ERROR_2 = "-2";

}

Или еще лучше использовать переменную enum.

Ответ 7

Я рекомендую комбинацию статического импорта и интерфейсов для констант.

Если интерфейс Java имеет постоянные объявления полей, имейте в виду, что они неявно публичны, статичны и окончательны (см. Спецификацию языка Java, Раздел 9.3.) Поэтому вы всегда можете опустить эти модификаторы, оставив только тип, и ваш постоянный интерфейс будет выглядеть следующим образом:

public interface Constants {
    int AGE = 0x23;
    String NAME = "Andrew";
    boolean IGNORE = true;
}

Это, конечно, следует использовать только так:

import static Constants.*;

public Whatever {
    public String method() {
        return String.format("%s is %d%c", NAME, AGE, IGNORE ? '?' : '!');
    }
}

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

Другая возможность, которую не каждый одобрит, - это вложить интерфейсы (или даже перечислять типы) в свой родительский интерфейс, что позволит вам группировать ваши константы. Это:

interface MoreConstants {
    int MAGIC = 0xCAFEBABE;
    interface PROPERTIES {
        String NAME = "name";
    }
    enum ERRORS {
        ON_FIRE, ASLEEP, BROKEN, UNSURE;
    }
}

и получить доступ к ним следующим образом: при условии статического импорта интерфейса MoreConstants:

if (!PROPERTIES.NAME.equals(value)) {
    return ERRORS.UNSURE;
}

Конечно, эти интерфейсы никогда не должны быть реализованы, что я считаю плохой практикой. Единственный способ гарантировать это, однако, является строгим обзором кода...

Ответ 8

Я лично считаю, что константы должны быть определены в классе по тем же причинам, что описаны выше. Тем более, что некоторые разработчики используют эти константы, реализуя интерфейс в классе, который хочет их использовать. Когда этот интерфейс содержит много констант, вы больше не хотите смотреть на javadoc этого конкретного класса, потому что он усеян описаниями констант, которые, вероятно, даже не используются этим классом.