Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / задачка: Java puzzle / 10 сообщений из 10, страница 1 из 1
21.01.2005, 12:27
    #32876857
concat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
задачка: Java puzzle
Дано:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
 public   abstract   class  A {
   public  A( int  i) {
    build(i);
  }
   protected   abstract   void  build( int  i);
}

 public   class  B  extends  A {
   private   int  size =  0 ;
   public  B( int  size) {
     super (size);
  }
   protected   void  build( int  size) {
     this .size = size;
  }
   public   int  size() {
     return  size;
  }
   public   static   void  main(String[] args) {
    B test =  new  B( 1 );
    System.out.println("Size: " + test.size());
  }
}
Output
------

Size: ???
...
Рейтинг: 0 / 0
21.01.2005, 12:45
    #32876935
А.Грасоff™
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
задачка: Java puzzle
ноль

--
Lacrima Mosa Est
...
Рейтинг: 0 / 0
21.01.2005, 12:48
    #32876948
А.Грасоff™
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
задачка: Java puzzle
объяснить почему? или ты знаешь, но решил людям голову поморочить?

--
Lacrima Mosa Est
...
Рейтинг: 0 / 0
21.01.2005, 13:05
    #32877017
concat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
задачка: Java puzzle
Задачка на то и была, объяснить почему ноль(извиняюсь, неточно сформулировала). И не для того, чтоб людям головы морочить, а чтоб знали и на такие грабли не наступали. :)
...
Рейтинг: 0 / 0
21.01.2005, 13:12
    #32877046
А.Грасоff™
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
задачка: Java puzzle
понятно.

ничего сложного.

последовательность выполнения действий:

1. конструктор класса В
1а. конструктор класса А
2. абстрактный метод build() класса А
2а. реализованный метод build() класса В, который присваивает внутреннему полю класса В int size значение 0
3. инициализация внутренних полей класса В определенными значениями. в данном случае полю B.size присваивается 0 (private int size = 0;)

решение проблемы:
- перенос поля size в родительский класс
- объявление полей класса без определения их значений (private int size;)

--
Lacrima Mosa Est
...
Рейтинг: 0 / 0
21.01.2005, 13:13
    #32877047
А.Грасоff™
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
задачка: Java puzzle
А.Грасоff™
2а. реализованный метод build() класса В, который присваивает внутреннему полю класса В int size значение 0


опечатка. должно быть:

2а. реализованный метод build() класса В, который присваивает внутреннему полю класса В int size значение 1
...
Рейтинг: 0 / 0
24.01.2005, 11:36
    #32879562
Ctrl+Alt+Delete
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
задачка: Java puzzle
объясните, что служит источником вызова метода build класса В?
помойму 0 получается именно потому, что вызов абстрактного метода build класса А не приводит в вызовы метода build класса B
...
Рейтинг: 0 / 0
24.01.2005, 11:41
    #32879584
А.Грасоff™
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
задачка: Java puzzle
Ctrl+Alt+Deleteобъясните, что служит источником вызова метода build класса В?
помойму 0 получается именно потому, что вызов абстрактного метода build класса А не приводит в вызовы метода build класса B
хы. измени в коде:

private int size = 0;

на

private int size;

и проверь свои догадки :)
...
Рейтинг: 0 / 0
24.01.2005, 11:49
    #32879614
zalexaka
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
задачка: Java puzzle
Ctrl+Alt+Deleteвызов абстрактного метода build класса А не приводит в вызовы метода build класса B
полиморфизьм батенька
...
Рейтинг: 0 / 0
27.01.2005, 11:29
    #32886536
funikovyuri
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
задачка: Java puzzle
Thinking in Java, 2nd edition, Revision 11
©2000 by Bruce Eckel
Конструкторы и полиморфизм
....
Поведение полиморфных методов внутри конструкторов
...
Понятно, что работа конструктора заключается в оживлении объектов (что на самом деле сродни подвигу). Внутри любого конструктора, целый объект может быть сформирован только по частям, Вы можете знать только то, что базовый объект был проинициализирован, но Вы не можете знать, какие классы наследованы от вашего класса. Динамически связываемые методы в произошедших от них классах. Если Вы сделаете такой фокус внутри конструктора, Вы вызовете метод, который может обрабатывать объекты, которые еще не были инициализированы. Хороший способ для создания катастрофы!

Вы можете разглядеть эту проблему в следующем примере:


//: c07:PolyConstructors.java
// Конструткоры и полиморфизм
// не производите то, что вы не можете ожидать.

abstract class Glyph {
abstract void draw();
Glyph() {
System.out.println("Glyph() before draw()");
draw();
System.out.println("Glyph() after draw()");
}
}

class RoundGlyph extends Glyph {
int radius = 1;
RoundGlyph(int r) {
radius = r;
System.out.println(
"RoundGlyph.RoundGlyph(), radius = "
+ radius);
}
void draw() {
System.out.println(
"RoundGlyph.draw(), radius = " + radius);
}
}

public class PolyConstructors {
public static void main(String[] args) {
new RoundGlyph(5);
}
} ///:~
В Glyph, метод draw( ) - abstract, так что он спроектирован для переопределения. В замен этого Вы принудительного переопределяете его в RoundGlyph. Но конструктор Glyph вызывает этот метод и этот вызов заканчивается в RoundGlyph.draw( ), что в общем-то выглядит как то, что было нужно. Но посмотрите на вывод:


Glyph() before draw()
RoundGlyph.draw(), radius = 0
Glyph() after draw()
RoundGlyph.RoundGlyph(), radius = 5
Когда конструктор Glyph-а вызывает draw( ), значение radius еще не приняло значение по умолчанию 1. Оно еще равно 0. Это означает, что не будет нарисована точка на экране, Вы будете пытаться нарисовать эту фигуру на экране и пытаться сообразить, почему программа не работает.


Порядок инициализации, описанный в предыдущей секции, не совсем полон и вот Вам ключ для разрешения этой загадки. Настоящий процесс инициализации:


Место отведенное под объекты инициализировано в ноль, до того, как что-то произойдет.
Вызывается конструктор базового класса (как и было описано ранее). В этот момент вызывается переопределенный метод draw( )(да, до того, как будет вызван конструткор RoundGlyph), который открывает, что значение radius равно нулю, как и было описано в шаге 1.
Инициализация элементов вызывается в порядке их определения.
Вызывается тело конструткора базового класса.
Это только вершина айсберга, поскольку все что еще не инициализировано является нулем (или заменителем нуля в специфичных типах данных), а не просто мусор. Сюда так же входят ссылки на объекты объявленные внутри класса через композицию, которые становятся null. Так что, если Вы забыли проинициализировать эти ссылки, то Вы получите исключение во время работы программы. Все остальное возвращает ноль, что обычно предательски отображается в выводе.


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


В качестве результата, хорошие руководящие принципы для конструктора "Делайте в конструкторе настолько меньше, насколько можете и если это возможно, то не вызывайте никаких методов". Существует только один тип методов, которые безопасно вызывать из конструктора, это final методы из базового класса. (Это так же применимо и к private методам, которые так же являются final.) Они не могут быть переопределены и поэтому не могут преподнести своего рода сюрприз.
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / задачка: Java puzzle / 10 сообщений из 10, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]