Страницы

Поиск по вопросам

вторник, 24 декабря 2019 г.

Где хранить константы в Java/Android?

#android #java


Здравствуйте.

Хочу писать правильный код, вот задался вопросом. Все-таки где же лучше хранить константы
в Java? Сейчас ковыряю коды стандартных приложений Android. Встретил для себя несколько
спорных моментов. Хочу задать несколько вопросов:


Где же все-таки лучше и правильнее хранить константы, которые используются часто
из других классов? 
Для чего используются private/protected interface? Они, в свою очередь, содержат
константы. Вот, например: 



  protected interface AlarmsColumns
  extends AlarmSettingColumns,
  BaseColumns


А класс, в котором объявлены такие интерфейсы, называется Contract(ClockContract).
Сами константы в интерфейсе объявлены как public static final. Изначально в коде программы
константы использовались так: 


  ClockContract.InstancesColumns._ID


Все было хорошо, если использовать из класса в одном пакете, а если класс находится
в другом пакете - при попытке доступа IDE писало вполне логичную ошибку, про доступ
к protected. Также заимплементить можно, только если находишься в одном пакете. 
Хотя, почитав официальные доки и интернет, хранение констант в интерфейсе считается
вроде антипаттерном. 

Объясните, пожалуйста, для чего было так сделано? Как работают protected/private
interface и где же всё-таки лучше хранить константы?
Спасибо заранее. 
    


Ответы

Ответ 1



Где же все-таки лучше и правильнее хранить константы, которые используются часто из других классов? В public static final полях класса или в public Enum'ах (как, например, тут и тут). Для чего используются private/protected интерфейсы. Они, в свою очередь, содержат константы ... для чего было так сделано Сделано это скорее всего, чтобы сгруппировать константы и ограничить к ним доступ. Не все константы должны быть доступны отовсюду, некоторые нужны только в классе, некоторые только в пакете и наследниках. как работают protected/private intrfaces Возьмём такую иерархию классов: |\ - Main.java | | - foo | |\ | | | - A.java | | | - B.Jjava | | | - C.java | | | | - bar | |\ | | | - D.java И код: // foo/A.java package foo; public class A { public static interface PublicInnerInterface { public static final int A_PUBLIC_INNER_INTERFACE_CONST = 0; } protected static interface ProtectedInnerInterface { public static final int A_PROTECTED_INNER_INTERFACE_CONST = 1; } private static interface PrivateInnerInterface { public static final int A_PRIVATE_INTERFACE_CONST = 2; } protected static class InnerClass { protected static final int A_PROTECTED_INNER_CLASS_CONST = 3; } protected static final int A_CONST = PrivateInnerInterface.A_PRIVATE_INTERFACE_CONST; } // foo/B.java package foo; public class B { public void test() { System.out.println("B -> A_PROTECTED_INNER_INTERFACE_CONST: " + A.ProtectedInnerInterface.A_PROTECTED_INNER_INTERFACE_CONST); System.out.println("B -> A_PROTECTED_INNER_CLASS_CONST: " + A.InnerClass.A_PROTECTED_INNER_CLASS_CONST); System.out.println("B -> A_CONST: " + A.A_CONST); } } // foo/C.java package foo; public class C extends A { public void test() { System.out.println("C -> A_PROTECTED_INNER_INTERFACE_CONST: " + ProtectedInnerInterface.A_PROTECTED_INNER_INTERFACE_CONST); System.out.println("C -> A_PROTECTED_INNER_CLASS_CONST: " + InnerClass.A_PROTECTED_INNER_CLASS_CONST); System.out.println("C -> A_CONST: " + A_CONST); } } // bar/D.java package bar; import foo.A; public class D extends A { protected static class InnerClass extends A.InnerClass { public static final int A_PROTECTED_INNER_CLASS_CONST = A.InnerClass.A_PROTECTED_INNER_CLASS_CONST + 10; } public void test() { System.out.println("D -> A_PROTECTED_INNER_INTERFACE_CONST: " + ProtectedInnerInterface.A_PROTECTED_INNER_INTERFACE_CONST); System.out.println("D -> A_PROTECTED_INNER_CLASS_CONST: " + InnerClass.A_PROTECTED_INNER_CLASS_CONST); System.out.println("D -> A_CONST: " + A_CONST); } } // Main.java import bar.D; import foo.A; import foo.B; import foo.C; public class Main { public static void main(String[] args) { System.out.println("Main -> A_PUBLIC_INNER_INTERFACE_CONST: " + A.PublicInnerInterface.A_PUBLIC_INNER_INTERFACE_CONST); B b = new B(); b.test(); C c = new C(); c.test(); D d = new D(); d.test(); } } A_PUBLIC_INNER_INTERFACE_CONST доступна везде A_PROTECTED_INNER_INTERFACE_CONST доступна классам, лежащим в том же пакете и классам-наследникам (даже из других пакетов). У наследников необязательно писать A. для доступа к внутренним классам/интерфейсам и статическим полям. A_PRIVATE_INTERFACE_CONST доступна только внутри класса A (в том числе, во внутренних class/interface/enum) A_PROTECTED_INNER_CLASS_CONST доступна классам, лежащим в том же пакете. Эта protected-константа недоступна напрямую наследникам, лежащим в других пакетах. Однако, сам защищённый класс доступен всем наследникам и можно отнаследоваться от него, чтобы получить значение этой константы (см. класс D). Имя можно задать другое (статические члены всё равно не наследуются), а можно и перезаписать с тем же именем. A_CONST доступна классам, лежащим в том же пакете и классам-наследникам (даже из других пакетов). Вообще, нет какого-то общего чёткого соглашения, всё зависит от смысла константы. Где хранить: В самом классе - если константа непосредственно связана с классом Во вложенном class/interface/enum - если несколько констант можно сгруппировать по-смыслу, но они всё-равно тесно связаны с самим классом В отдельном class/interface/enum - если несколько констант можно сгруппировать, но они имеют смысл вне какого-либо класса Какой поставить доступ: public - если константа широко используется другими классами protected - если константа используется внутри пакета или имеет смысл разрешить использовать её в классах-наследниках, ограничив доступ всем остальным private - если константа используется только внутри класса

Комментариев нет:

Отправить комментарий