Участник
Регистрация: 28.11.2005
Адрес: Москва
|
Цитата:
Сообщение от Владимир Максимов
Как мне кажется, происходит путаница понятий. В системе Axapta создание объекта - это командаX++: myVar = new MyObject() Кажется, что команда new вызывает непосредственно метод new() объекта. Однако если бы это было действительно так, то внутри метода new() объекта невозможно было бы сделать присвоение свойствам этого объекта или вызвать метод объекта.
Давайте, чтобы не создавать еще большую путаницу, немного уточним терминологию. Я применительно к языку Х++ не встречал упоминания термина "команда". В ОО-языках, таких как C++/C#, это называется оператор new; в том же С++ есть также операторы delete и delete[], служащие для освобождения выделенной под объект памяти, но в C#/X++ с их автоматических управлением памятью они не актуальны и, соответственно, отсутствуют. Еще в ОО-языках есть понятие конструкторов и деструкторов, которые вызываются, соответственно, при создании объекта (оператором new) и при его удалении (оператором delete, или сборщиком мусора, или еще кем). Путаница в случае Х++ возникает из-за того, что оператор new и конструктор new() называются одинаково; в моем предыдущем сообщении в этой теме, пожалуй, действительно смешались эти два понятия. Тем не менее, в Х++ вызов оператора new непосредственно ведет к вызову конструктора new().
Цитата:
Сообщение от Владимир Максимов
Т.е. внутри метода new() экземпляр объекта уже существует. Внутри метода new() объекта вполне допустимо обращение к методам этого объекта через this.MyMethod().
На мой взгляд, экземпляр объекта до завершения работы конструктора (а new() и finalize() в Х++ от прочих методов отличаются именно тем, что это конструктор и декструктор) все же не существует. Хотя, это вопрос философский: можно ли называть, к примеру, сооружение без крыши домом или конструкцию без двигателя - автомобилем? 
К слову, в зависимости от реализации класса обращения к тем или иным методам внутри конструктора могут привести к некорректным результатам, если методы предполагают, что конструктор уже отработал, и какие-то внутренние структуры или объекты уже инициализированы - это опять же к вопросу о том, когда кусок выделенной памяти становится объектом.
Цитата:
Сообщение от Владимир Максимов
Это означает, что конструирование объекта Axapta происходит ДО вызова метода new() этого же объекта. Просто разработчики Axapta предоставили возможность ПОСЛЕ конструирования объекта добавить некий код.
Гхм... в моем понимании «конструирование объекта» осуществляется в общем случае его конструктором, а не, к примеру, оператором выделения памяти для объекта. И если объект не находится на вершине иерархии наследования, и при этом успели отработать лишь некоторые из конструкторов его базовых классов, то нельзя говорить о том, что объект уже создан. А в случае с классами в Аксапте иерархия наследования отнюдь не начинается с какого-либо класса, реализованого на Х++.
Если посмотреть, что происходит непосредственно в ядре, то увидим следующее:- интерпретатор байт-кода (экземпляр класса interpret) встречает в байт-коде символ, соответствующий ключевому слову new и вызывает обработчик этого символа - метод interpret::xal_new_sym(void) (поскольку ядро написано на С++, будем здесь пользоваться нотацией этого языка);
- interpret::xal_new_sym(), в свою очередь, вызывает метод interpret::eval_new(cqlClass**,ushort), после чего инициализирует несколько полей созданного объекта;
- interpret::eval_new() сначала выделяет фиксированный объем памяти размером 56 (для AX3) или 60 (для AX4) байт, используя оператор new из библиотеки времени выполнения С++, который, в случае ядра Аксапты, вызывает соотв. метод выделения памяти библиотеки SmartHeap;
- после выделения памяти вызывается конструктор cqlClass::cqlClass(ushort), который заполняет выделенный участок памяти нулями и инициализирует некоторые служебные данные этого класса;
- затем увеличивается счетчик ссылок на сам созданный объект, а также глобальный счетчик ссылок, используемый, в частности, классом HeapCheck;
- наконец, происходит самое интересное - вызов конструктора new() создаваемого объекта, причем, поскольку все классы наследуют от Object, то констурктор вызывается всегда - либо определенный для данного класса или его предка, либо конструктор по умолчанию класса Object.
Цитата:
Сообщение от Владимир Максимов
С точки зрения разработчика - нет никакой разницы где именно писать код инициализации параметров объекта. В событии new() объекта или в методе init().
В корне не согласен. Если рассматривать вопрос проектирования классов с точки зрения контрактной модели программирования, то инициализация объекта не может быть необязательной, если это не предусмотрено протоколом взаимодействия с объектом. Т.е., пользуясь данной терминологией, если инициализация объекта необходима для выполнения им контракта, а вы, проектируя и реализуя класс, даете возможность не выполнять эту инициализацию, то вы закладываете возможность нарушения объектом данного класса своего контракта при соблюдении протокола взаимодействия с ним.
По поводу контрактной модели см., например, Объектно-ориентированный анализ и проектирование Гради Буча.
Последний раз редактировалось gl00mie; 09.07.2008 в 15:12.
Причина: typo
|