воскресенье, 23 января 2011 г.

Java: Вызов переопределенных методов в конструкторе

Подобная проблема, по-моему описывалась Блохом, но я изложу ее на русском и со своей стороны. Имеем родительский класс с полем, значение которого инициализируется в конструкторе (логика обычно простая). По правилам хорошего тона эта логика вынесена в отдельный метод. Поле после инициализации больше не используется для записи и поэтому final.
Спустя какое-то время появляется наследник класса у которого логика инициализации поля field другая. Для этого модификатор доступа меняется на protected, чтобы дать возможность наследнику заложить туда свою логику. Итак, получаем:
  1. static class Parent {
  2.         private final String field;
  3.  
  4.         Parent() {
  5.             field = createField();
  6.         }
  7.  
  8.         protected String createField() {
  9.             return "Parent-impl";
  10.         }
  11.  
  12.         @Override
  13.         public String toString() {
  14.             return getClass().getSimpleName() + field;
  15.         }
  16.     }
  17.  
  18.  
  19.     static class Child extends Parent {
  20.         private final String leftPart, rightPart;
  21.  
  22.         Child(String left, String right) {
  23.             leftPart = left;
  24.             rightPart = right;
  25.         }
  26.  
  27.         @Override
  28.         protected String createField() {
  29.             return leftPart + rightPart;
  30.         }
  31.     }
  32.  
  33.     public static void main(String[] args) {
  34.         System.out.println(new Child("AB", "CD"));

По результатам кажется что main должен вернуть ABCD. Однако это не так. Проблема в том, что в логике переопределенного метода createField() не должны участвовать состояния как наследника, так и родителя. Проще говоря можно использовать только константы (statiс final), хотя и с ними надо быть осторожным. Почему? Дело в том, что на момент вызова метода поля его + родительские поля создаваемого экземпляра еще не до конца созданы. В данном примере в момент вызова Child.createField() поля leftPart и rightPart ещё не проинициализированы (хотя они и final) и равны null.

Как теперь это исправить?
Есть несколько способов, я предпочитаю работать вместо поля с методом и как следствие вынести инициализацию в "ленивую" секцию. Как-то так:
  1. static class Parent {
  2.         private final String field;
  3.  
  4.         Parent() {
  5.             field = createField();
  6.         }
  7.  
  8.         private String createField() {
  9.             return "Parent-impl";
  10.         }
  11.  
  12.         protected String getField() {
  13.             return field;
  14.         }
  15.  
  16.         @Override
  17.         public String toString() {
  18.             return getClass().getSimpleName() + getField();
  19.         }
  20.     }
  21.  
  22.  
  23.     static class Child extends Parent
  24.  
  25.     {
  26.         private final String leftPart, rightPart;
  27.  
  28.         Child(String left, String right) {
  29.             leftPart = left;
  30.             rightPart = right;
  31.         }
  32.  
  33.         @Override
  34.         protected String getField
  35.                 () {
  36.             return leftPart + rightPart;
  37.         }
  38.     }
  39.  
  40.     public static void main(String[] args) {
  41.         System.out.println(new Child("AB", "CD"));

вторник, 18 января 2011 г.

GSM 5G что хотелось бы иметь

Что бы я добавил в стандарт сотовой связи GCM 5G.


1. Автоматический перевод телефонов в режим вибрации в театрах, кино, залах конференций и подобных местах. В общем, там, где все время просят их отключить, но всегда кто-нибудь да забудет или проигнорирует. Сота шлет сигнал телефону - мол, заткнись - и он затыкается. В идеале конечно позиционировать абонента и делать это именно когда он находится непосредственно в "тихом" помещении - чтобы в коридоре "громкий" режим телефона возвращался обратно.

2. Как продолжение предыдущего пункта, сота должна уметь выключать GSM модуль в самолетах / больницах и других серьезных местах. Возникает правда вопрос - а как его обратно автоматически включить, если GSM модуль отключен? Как вариант, сота сообщает телефону через какое количество времени телефон должен вернуться в строй. Для самолетов такое точно бы работало, для больниц - не знаю...


3. Способность GSM модулям телефонов связываться напрямую друг с другом если они в пределах досягаемости одной соты. Такой peer-2-peer для соседей. Телефон тогда бы отсылал на соту только тарификационные данные - поговорил с абонентом таким-то столько-то минут и секунд. Это бы решило проблему связи в большой толпе когда все друг другу звонят. Ну и конечно снизило нагрузку на соты в какой-то мере.

4. В адресной книге - статусы абонентов как в аське / скайпе. Чтобы не звонить и слышать "абонент временно недоступен" - видеть сразу что человека нет в сети. В статусе также можно было бы писать имя оператора, местоположение, в роуминге ли абонент или нет, ну и много чего еще интересного.

5. Ну и то, что уже наверняка есть на Android - автоподключение к халявным Wi-Fi сетям поблизости. Иметь базу городских точек с бесплатным Wi-Fi и просто определать их по местоположению.