|
|
|
задачка: Java puzzle
|
|||
|---|---|---|---|
|
#18+
Дано: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. ------ Size: ??? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.01.2005, 12:27 |
|
||
|
задачка: Java puzzle
|
|||
|---|---|---|---|
|
#18+
ноль -- Lacrima Mosa Est ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.01.2005, 12:45 |
|
||
|
задачка: Java puzzle
|
|||
|---|---|---|---|
|
#18+
объяснить почему? или ты знаешь, но решил людям голову поморочить? -- Lacrima Mosa Est ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.01.2005, 12:48 |
|
||
|
задачка: Java puzzle
|
|||
|---|---|---|---|
|
#18+
Задачка на то и была, объяснить почему ноль(извиняюсь, неточно сформулировала). И не для того, чтоб людям головы морочить, а чтоб знали и на такие грабли не наступали. :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.01.2005, 13:05 |
|
||
|
задачка: Java puzzle
|
|||
|---|---|---|---|
|
#18+
понятно. ничего сложного. последовательность выполнения действий: 1. конструктор класса В 1а. конструктор класса А 2. абстрактный метод build() класса А 2а. реализованный метод build() класса В, который присваивает внутреннему полю класса В int size значение 0 3. инициализация внутренних полей класса В определенными значениями. в данном случае полю B.size присваивается 0 (private int size = 0;) решение проблемы: - перенос поля size в родительский класс - объявление полей класса без определения их значений (private int size;) -- Lacrima Mosa Est ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.01.2005, 13:12 |
|
||
|
задачка: Java puzzle
|
|||
|---|---|---|---|
|
#18+
А.Грасоff™ 2а. реализованный метод build() класса В, который присваивает внутреннему полю класса В int size значение 0 опечатка. должно быть: 2а. реализованный метод build() класса В, который присваивает внутреннему полю класса В int size значение 1 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.01.2005, 13:13 |
|
||
|
задачка: Java puzzle
|
|||
|---|---|---|---|
|
#18+
объясните, что служит источником вызова метода build класса В? помойму 0 получается именно потому, что вызов абстрактного метода build класса А не приводит в вызовы метода build класса B ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.01.2005, 11:36 |
|
||
|
задачка: Java puzzle
|
|||
|---|---|---|---|
|
#18+
Ctrl+Alt+Deleteобъясните, что служит источником вызова метода build класса В? помойму 0 получается именно потому, что вызов абстрактного метода build класса А не приводит в вызовы метода build класса B хы. измени в коде: private int size = 0; на private int size; и проверь свои догадки :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.01.2005, 11:41 |
|
||
|
задачка: Java puzzle
|
|||
|---|---|---|---|
|
#18+
Ctrl+Alt+Deleteвызов абстрактного метода build класса А не приводит в вызовы метода build класса B полиморфизьм батенька ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.01.2005, 11:49 |
|
||
|
задачка: Java puzzle
|
|||
|---|---|---|---|
|
#18+
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.) Они не могут быть переопределены и поэтому не могут преподнести своего рода сюрприз. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.01.2005, 11:29 |
|
||
|
|

start [/forum/topic.php?fid=59&msg=32876948&tid=2153035]: |
0ms |
get settings: |
8ms |
get forum list: |
16ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
50ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
47ms |
get tp. blocked users: |
1ms |
| others: | 208ms |
| total: | 347ms |

| 0 / 0 |
