tag:blogger.com,1999:blog-33057655.post7116633620065510485..comments2022-03-02T02:08:08.083+03:00Comments on Разное от программиста...: Delphi 2010. RTTI.Kazantsev Alexeyhttp://www.blogger.com/profile/14086309924481739588noreply@blogger.comBlogger10125tag:blogger.com,1999:blog-33057655.post-66965519612783178922010-09-28T00:23:47.709+04:002010-09-28T00:23:47.709+04:00>Стоп, смотрю http://edn.embarcadero.com/articl...>Стоп, смотрю http://edn.embarcadero.com/article/34324, раздел Operator Overloading - как раз для классов сделано. Это не работает?<br /><br />Работает только для .NET-версий Delphi. Нативная Delphi этого не поддерживает.<br /><br />>Для языка высокого уровня - несомненный архаизм, наряду с goto.<br /><br />Будучи высокоуровневым языком, Delphi позволяет использовать любые низкоуровневые трюки, что выгодно отличает его от современного мейнстрима. Авторы языка это понимают, и не только не отрекаются от низкоуровневости, но еще и делают ее более удобной ($POINTERMATH, как пример)<br /><br />>Подобное приведение типов, думаю, лучше реализовывать через записи с вариантами.<br /><br />Это не избавит от необходимости делать приведение типов: TMyVarRec(Value).NativeInt; TMyVarRec(Value).Pointer;<br /><br />>С absolute можно легко залезть в чужую память, особенно при изменении размеров типов.<br /><br />Главное не забывать стелить соломку:<br />Class Operator XmlRpcBinary.Implicit(Const AValue : Variant) : XmlRpcBinary;<br /><br />{$REGION ' Контроль размера типа '}<br /><br /> {$IF SizeOf(XmlRpcValue) <> SizeOf(Variant)}<br /><br /> {$MESSAGE FATAL 'Absolute. SizeOf(XmlRpcValue) <> SizeOf(Variant)'}<br /><br /> {$IFEND}<br /><br />{$ENDREGION}<br /><br />Var<br /><br /> Value : XmlRpcValue Absolute AValue;<br /><br />>Пример использования в справке Delphi<br /><br />var<br />Str: string[32];<br />StrLen: Byte absolute Str;<br /><br />по моему мнению - аккуратно разложенные грабли. Premature optimization в чистом виде.<br /><br />Этому примеру сто лет в обед :) Правда, сейчас так давно никто не делает, в этом нет нужды.<br /><br />Я приведу еще пример кода, когда absolute помогает облегчить, и написание кода, и его чтение:<br />Function EncodeBase64(Const AData; ADataSize : Integer; Const ABuffer; ABufferSize : Integer) : Integer;<br /><br />Var<br /><br /> Data : PAnsiChar Absolute AData;<br /> Buffer : PAnsiChar Absolute ABuffer;<br /><br />Внутри функции работать удобнее именно с PAnsiChar т.к. появляется возможность адресоваться к чарам, как к элементам массива + адресная арифметика.Kazantsev Alexeyhttps://www.blogger.com/profile/14086309924481739588noreply@blogger.comtag:blogger.com,1999:blog-33057655.post-11015472481645689462010-09-27T22:03:24.956+04:002010-09-27T22:03:24.956+04:00> Перегрузка операторов это самое большое преим...> Перегрузка операторов это самое большое преимущество записей перед классами.<br />Стоп, смотрю http://edn.embarcadero.com/article/34324, раздел Operator Overloading - как раз для классов сделано. Это не работает?<br /><br />> Какой же это архаизм?<br />Для языка высокого уровня - несомненный архаизм, наряду с goto.<br />Подобное приведение типов, думаю, лучше реализовывать через записи с вариантами. С absolute можно легко залезть в чужую память, особенно при изменении размеров типов. <br /><br />Пример использования в справке Delphi<br /><br />var<br /> Str: string[32];<br /> StrLen: Byte absolute Str;<br /><br />по моему мнению - аккуратно разложенные грабли. Premature optimization в чистом виде.<br />--<br />EugeneAnonymousnoreply@blogger.comtag:blogger.com,1999:blog-33057655.post-20564394949554651562010-09-26T14:04:44.682+04:002010-09-26T14:04:44.682+04:00>Вы сравниваете record vs object, а я record vs...>Вы сравниваете record vs object, а я record vs class. Вашу позицию я понял.<br /><br />Перегрузка операторов это самое большое преимущество записей перед классами. Кроме того, отсутствие необходимости в динамическом размещении делает записи очень удобными для "мелкой инкапсуляции", что можно увидеть на примере TStopwatch, использовать который, будь он в виде класса, было бы чрезвычайно неудобно.<br /><br />>В любом случае, им стоило выбросить object из языка, но к сожалению, они будут тащить его и дальше<br /><br />Они как то делились планами по поводу переписывания компилятора с выкидыванием накопленного мусора. Возможно object и выкинут.<br /><br />>наряду с архаизмами вроде absolute.<br /><br />Какой же это архаизм? Очень удобная вещь, когда не хочется трехэтажных приведений типов, или когда приведение сделать невозможно.<br /><br />>Такое ощущение, что сложность языка и компилятора в последних версиях уже вышла из под контроля, и подобные грабли будут попадаться постоянно.<br /><br />Согласен. Не зря они собирались компилятор переписать :) А тут еще x64 и кроссплатформа...Kazantsev Alexeyhttps://www.blogger.com/profile/14086309924481739588noreply@blogger.comtag:blogger.com,1999:blog-33057655.post-55782447870885227972010-09-26T11:53:05.127+04:002010-09-26T11:53:05.127+04:00> Дело не только в хранении данных. Есть необхо...> Дело не только в хранении данных. Есть необходимость в интеропе с внешними API, тут классы не помогут (класс, суть черный ящик с публичным интерфейсом). <br /><br />Класс - фактически та же запись, вернее указатель на нее. Впрочем, действительно, классы для взаимодействия с внешними библиотеками использовать не принято. Возможно, и зря. Если разработчики обеспечили бы гарантии выравнивания полей в классе a la record (не знаю, как сейчас), то можно было бы обойтись и классом.<br /><br />> Перегрузка операторов, в нативной Delphi (о призме я не говорю), реализована только для записей.<br /><br />Вы сравниваете record vs object, а я record vs class. Вашу позицию я понял. В любом случае, им стоило выбросить object из языка, но к сожалению, они будут тащить его и дальше, наряду с архаизмами вроде absolute.<br /><br />Такое ощущение, что сложность языка и компилятора в последних версиях уже вышла из под контроля, и подобные грабли будут попадаться постоянно. <br />--<br />EugeneAnonymousnoreply@blogger.comtag:blogger.com,1999:blog-33057655.post-56280558348813898622010-09-26T03:50:41.570+04:002010-09-26T03:50:41.570+04:00>А причем здесь records ? Их же для классов не ...>А причем здесь records ? Их же для классов не реализовывали разве?<br /><br />Перегрузка операторов, в нативной Delphi (о призме я не говорю), реализована только для записей.<br /><br />>> А хелперы?<br />>То же самое - к записям отношения не имеет.<br /><br />Объекты (object) не могут иметь хелперов, записи могут.<br /><br />>Насчет полезности helpers у меня сомнения - слишком сильное нарушение инкапсуляции, так как мы можем "взломать" любой класс, не утруждая себя проектированием.<br /><br />Хелперы могут сильно облегчить жизнь при работе с чужим кодом. Никакого взлома при этом, разумеется, не происходит т.к. за рамки публичных интерфейсов выйти не удастся в любом случае.<br /><br />>Вернемся к записям. В Delphi сейчас есть классы (class), есть записи (record) и есть объекты (object). И object, и record размещаются в статической памяти и не имеют общего предка. И в чем тогда разница?<br /><br />Записи поддерживают перегрузку операторов, объекты (object) нет. Записи могут иметь хелперы, объекты (object) не могут.<br /><br />>Advanced records - мало того что реинкарнация object, так еще и новая синтаксическая конструкция.<br /><br />Скорее, просто расширенная ;)<br /><br />>Для хранения данных вполне подходил class - накладные расходы 4 байта (правда, в последних версиях вроде 8), но зато общий предок и конструкторы/деструкторы.<br /><br />Дело не только в хранении данных. Есть необходимость в интеропе с внешними API, тут классы не помогут (класс, суть черный ящик с публичным интерфейсом). А продвинутые структуры позволяют нам увеличить инкапсуляцию при работе с данными (это наглядно демонстрирует хэлпер для TRTLCriticalSection из SyncObjs)<br /><br />>Что же до издержек на создание экземпляра класса в динамической памяти, то можно попробовать<br />реализовать пул экземпляров, переопределив NewInstance у данного class type.<br /><br />На самом деле издержки не столь велики, FastMM прекрасно справляется. Я пробовал делать пул часто создаваемых объектов для своей реализации пула потоков. Затея оказалась напрасной. Пул объектов работал ни чуть не быстрее обычной аллокации.Kazantsev Alexeyhttps://www.blogger.com/profile/14086309924481739588noreply@blogger.comtag:blogger.com,1999:blog-33057655.post-17002008178592702782010-09-25T22:04:05.179+04:002010-09-25T22:04:05.179+04:00> А как же перегрузка операторов?
А причем здес...> А как же перегрузка операторов?<br />А причем здесь records ? Их же для классов не реализовывали разве?<br />> А хелперы?<br />То же самое - к записям отношения не имеет.<br /><br />Насчет полезности helpers у меня сомнения - слишком сильное нарушение инкапсуляции, так как мы можем "взломать" любой класс, не утруждая себя проектированием. Разработчики предупреждали:<br />"Class helpers provide a way to extend a class, but they should not be viewed as a design tool to be used when developing new code. They should be used solely for their intended purpose, which is language and platform RTL binding."<br />(http://edn.embarcadero.com/article/34324). <br /><br />Вернемся к записям. В Delphi сейчас есть классы (class), есть записи (record) и есть объекты (object). И object, и record размещаются в статической памяти и не имеют общего предка. И в чем тогда разница? Object имеет статус "backward compatibility only", т.е. планировалось, что его полностью заменит class. <br />Advanced records - мало того что реинкарнация object, так еще и новая синтаксическая конструкция.<br /><br />Для хранения данных вполне подходил class - накладные расходы 4 байта (правда, в последних версиях вроде 8), но зато общий предок и конструкторы/деструкторы.<br /><br />Что же до издержек на создание экземпляра класса в динамической памяти, то можно попробовать<br />реализовать пул экземпляров, переопределив NewInstance у данного class type.<br />--<br />EugeneAnonymousnoreply@blogger.comtag:blogger.com,1999:blog-33057655.post-46244440520325436892010-09-24T23:14:58.857+04:002010-09-24T23:14:58.857+04:00А как же перегрузка операторов? А хелперы? Чрезвыч...А как же перегрузка операторов? А хелперы? Чрезвычайно удобные штуки, от которых пришлось бы отказаться.Kazantsev Alexeyhttps://www.blogger.com/profile/14086309924481739588noreply@blogger.comtag:blogger.com,1999:blog-33057655.post-25736056836234970202010-09-24T22:44:10.053+04:002010-09-24T22:44:10.053+04:00Неясно, зачем вообще нужны advanced records - чем ...Неясно, зачем вообще нужны advanced records - чем TObject не устраивает?<br />Тип record хорошо вписывается в процедурное программирование, жаль, что там его и не оставили. Нет, ведь нужно было делать аналог struct в С++<br />:(Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-33057655.post-21106837579564375392009-10-19T13:15:54.105+04:002009-10-19T13:15:54.105+04:00RTTI для записей тем не менее существует, поля то ...RTTI для записей тем не менее существует, поля то получить можно. Какого они не сделали этого для свойств...Kazantsev Alexeyhttps://www.blogger.com/profile/14086309924481739588noreply@blogger.comtag:blogger.com,1999:blog-33057655.post-4834635884368372632009-10-19T12:30:32.623+04:002009-10-19T12:30:32.623+04:00В делфях RTTI заточены на таблице VMT. Если нет VM...В делфях RTTI заточены на таблице VMT. Если нет VMT, то в рантайме ее неоткуда брать, кроме той что может вставить компилятор. По этой же причине не работают свойства в старых объектах, пока не добавишь хотя бы один виртуальный метод.Anonymousnoreply@blogger.com