Перейти из форума на сайт.

НовостиФайловые архивы
ПоискАктивные темыТоп лист
ПравилаКто в on-line?
Вход Забыли пароль? Первый раз на этом сайте? Регистрация
Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Вопросы по Embarcadero RAD Studio XE4

Модерирует : ShIvADeSt

 Версия для печати • ПодписатьсяДобавить в закладки
Страницы: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39

Открыть новую тему     Написать ответ в эту тему

Eternal_Shield

Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
RuXandr
А так быстрее и меньше памяти жрёт:

Код:
 
procedure TForm1.Button1Click(Sender: TObject);  
 var  
   btn: TButton absolute Sender;  
 begin  
   if Sender is TButton then  
     btn.Caption := 'ok';  
 end;
 


Всего записей: 767 | Зарегистр. 18-05-2009 | Отправлено: 19:43 13-06-2013
AlekXL



Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

Цитата:
Ну, коллеги - хоть кто то может мне сказать, почему у классов из System.Generics.Collections (например, TObjectList <T>) все методы - не виртуальные?! То есть я не могу их переопределить, чтобы добавить нужное мне поведение! Ну вот какая логика-то в этом была, когда это делали?
 

аллах с ними. Есть куда более мощные библиотеки контейнеров. Как есть и для шарпа C5 либа.
 у меня новая заморочка

Код:
 
  readSuccess:=ReadFileEx(Handle,Addr(Buffer),count,Addr(request.Overlapped),@FileIOCompletionRoutine );
    //readFileEx result is quite meaningless
    err:=GetLastError();
   //if readSuccess==true, then operation completed synchronously
    Inc(tries);
    readSuccess:= (err=ERROR_SUCCESS) or (err=ERROR_IO_PENDING) or (err=ERROR_IO_INCOMPLETE);
 

файл читается маленький, 17 килобайт, и из-за это в count усекался по размеру файла. Я получал
err=87, что-то вроде "Параметр задан неверно". Захардкодил места count -1024 - получил ERROR_SUCCESS
закоментировал усечение count ( так чтоб он равнялся всему размеру буфера, 64KB -ERROR_SUCCESS)
То есть требуется, чтобы nNumberOfBytesToRead был кратным чему-то? Нигде в документации не встречал.
------
и еще одна есть два интерфейса

Код:
 
 IovRequestWin=interface(IovRequest)
   ['{19EB993E-1D96-4F0C-9BAB-743BE38CF708}']
  function getOverlapped():TOverlapped;
  property Overlapped:TOverlapped read getOverlapped;
end;
 

и

Код:
 
 IovRequest=interface
 ['{1B282163-8DB7-450C-9C31-2DD75EA27A96}']
  function IsPending():Boolean;
  function  GetResult():TovResult;
  function getOnRequestFinished():TRequestCallback;
  procedure setOnRequestFinished(handler:TRequestCallback);
  function Wait(timeOut:Cardinal=5000):TWaitResult;
  function getBytesDone():integer;
  function EnsureDone():TovResult;
 end;
 

 
и класс

Код:
 
 TRequest = class(TMyInterfacedObject,IovRequestWin)
 
 

мне нужно вернуть  TRequest в качестве IovRequest.  
 
Присваивание не работает, внезапно. Код

Код:
 
 Assert( request.GetInterface(IovRequest,Result));
 

выдает EAssertion
 
только грязный

Код:
 
 Assert( request.GetInterface(IovRequestWin,Result));
 

срабатывает, но не уверен, что все там корректно...
Как это сделать элегантно?

Всего записей: 792 | Зарегистр. 24-04-2008 | Отправлено: 20:20 13-06-2013 | Исправлено: AlekXL, 20:21 13-06-2013
valgreesh



Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
AlekXL

Цитата:
TRequest = class(TMyInterfacedObject,IovRequestWin)  


Цитата:
мне нужно вернуть  TRequest в качестве IovRequest. Присваивание не работает, внезапно. Код  

Оно правильно не работает. Чтоб работало (хоть присваивание, хоть запрос), поддержку интерфейса классом нужно декларировать явно:
 

Код:
TRequest = class(TMyInterfacedObject, IovRequest, IovRequestWin)

Всего записей: 292 | Зарегистр. 30-11-2011 | Отправлено: 23:53 13-06-2013
ego666

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

Цитата:
Ну, коллеги - хоть кто то может мне сказать, почему у классов из System.Generics.Collections (например, TObjectList <T>) все методы - не виртуальные?! То есть я не могу их переопределить, чтобы добавить нужное мне поведение!

Ты бредишь.

Код:
  TCollectionNotification = (cnAdded, cnRemoved, cnExtracted);
 
  TObjectList<T: class> = class(TList<T>)
    ...
  protected
    procedure Notify(const Value: T; Action: TCollectionNotification); override;

 
Добавлено:

Цитата:
То есть требуется, чтобы nNumberOfBytesToRead был кратным чему-то? Нигде в документации не встречал.

Судя по комментариям на MSDN буфер вроде, как должен быть кратен сектору тома.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa365467(v=vs.85).aspx
 
Также об этом говорится тут (и странно, что на самом MSDN об этом не говорится), но оговаривается что это только для случаев, когда файл открывается с FILE_FLAG_NO_BUFFERING.
http://www.vsokovikov.narod.ru/New_MSDN_API/Menage_files/fn_readfileex.htm

Всего записей: 77 | Зарегистр. 14-06-2013 | Отправлено: 05:35 14-06-2013
andrewtishkin



Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
ego666
Цитата:
и странно, что на самом MSDN об этом не говорится
MSDN-библиотечку уже не раз неслабо перелопатили, частенько с потерей информации. Лирическое отступление про наболевшее с LCIDами. Поэтому удобнее и полезнее бывает пользоваться ещё и актикварной документацией, даже времён Win98.
 
Но в данном случае они не совсем кастрировали старый текст, просто вынесли эти подробности в отдельную статью:
Цитата:
There are strict requirements for successfully working with files opened with CreateFile using FILE_FLAG_NO_BUFFERING. For details see File Buffering.

PS: Соковиков, кстати, про свой перевод на главной говорит, что
Цитата:
основой для переведенных статей, описания функций, макрокоманд, сообщений, уведомлений и структур и т. д. стал выпуск Библиотеки MSDN от января 2005 и 2008 года, а не справка к какому либо компилятору
Ещё та MSDN Library, которую можно было скачать в виде .iso-шек

Всего записей: 781 | Зарегистр. 28-08-2008 | Отправлено: 07:50 14-06-2013 | Исправлено: andrewtishkin, 07:59 14-06-2013
deks



Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
ego666
 

Цитата:
Ты бредишь.  

 
Ну - будем говорить про отличие в ПЕРЕОПРЕДЕЛЕНИИ методов и получение уведомлений о действиях? Как вы через нотификацию сможете переопределить TList.Count, например, для реализации LazyLoad списка файлов/папок по доступу к Count? Внимательнее))

Всего записей: 857 | Зарегистр. 09-10-2003 | Отправлено: 11:47 14-06-2013
ego666

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
deks
Если хочется странного, то нужно писать собственный класс списка, удовлетворяющий требованиям. Стандартный TList удобен и прост и его возможностей вполне хватает для большинства обычных задач и не нужно его уродовать.
 
P.S.
А проперти в наследниках можно перекрывать, собственно так раньше без дженериков и делали.

Всего записей: 77 | Зарегистр. 14-06-2013 | Отправлено: 13:13 14-06-2013 | Исправлено: ego666, 13:16 14-06-2013
deks



Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
ego666
 
Спасибо, КЭП. То есть отличие между нотификациями и наследованием мы уже поняли. Хорошо.
 
А теперь - что ж странного то в желании задействовать стандартный список для управления списоком файлов и папок? На мой взгляд - странно как раз то, что этого сделать нельзя. В Java/ObjC можно. А в Дельфи приходится делать свой велосипед. При этом, велосипед не будет совместим со стандратным списком (там, где используется стандартный список - его использовать будет нельзя).  
 
Чем "изуродует" стандартный TList добавление ко всем методам слова virtual я не понимаю.
 
Единственная мотивация, которую я придумал - это наличие некоторой оптимизации в скорости вызова метода/размере памяти для не-виртуальных методов списка. Хотя при желании экономить я бы сделал в RTL особенную, не виртуальную версию списка, а для обычных применений использовал бы виртуальную.
 
Насчет перекрывать проперти в наследниках - если обращаться к экземпляру объекта через ссылку с родительским типом, перекрытые проперти "не сработают", так как будут вызваны родительские геттеры-сеттеры. Для этого и нужны виртуальные методы для геттеров и сеттеров. Не ясно при чем тут дженерики! Дженерик - это способ сделать вариацию класса на заданную тему, а не изменить поведение существующего класса.  
 
 
 
Добавлено:
Eternal_Shield
RuXandr
 
В Oxygene обнаружилась для похожих вариантов две конструкции, которые генерируют безопасный код. Зацените:
 

Код:
with matching obj := TButton(Sender) do obj.Caption := 'ok';

 
и
 

Код:
TButton(Sender):Caption := 'ok';

 
В обоих случаях каст T() дает nil при невозможности каста.  
 
При этом в первом случае блок "with matching" будет вызван только если obj инициализирован (не nil).
 
Во втором случае colon notation для вызова проверяет левую часть насчет nil, и вызов делает только если все ок.
 
Имхо, элегантно, да.  

Всего записей: 857 | Зарегистр. 09-10-2003 | Отправлено: 14:00 14-06-2013 | Исправлено: deks, 14:16 14-06-2013
ego666

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
deks
ещё раз, хочешь странного - пиши сам или бери готовое (коллекции от Ciobanu Alexandru, там и как в джаве и как шарпе). Мне и 99% программистам в 99% случаев вполне хватает стандартных списков.
 

Цитата:
Чем "изуродует" стандартный TList добавление ко всем методам слова virtual я не понимаю.

одними приписками не обойдёшься, TList хранит элементы тупо в массиве, нужно будет всё менять.
 
Добавлено:

Цитата:
Оно правильно не работает. Чтоб работало (хоть присваивание, хоть запрос), поддержку интерфейса классом нужно декларировать явно

Заранее поясню, так делать обязывает COM. Что кстати даёт Делфи дополнительные плюшки, перед другими языками (джава, шарп вроде тоже, с++ (ну у него вообще их нет)), где у интерфейсов наследование такое же как и у классов.

Всего записей: 77 | Зарегистр. 14-06-2013 | Отправлено: 16:10 14-06-2013 | Исправлено: ego666, 16:22 14-06-2013
deks



Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
ego666

Цитата:
хочешь странного

Ну - если удобный стандартный контейнер для дельфи является странным, то ок. А по мне странно то, что в других платформах можно использовать стандартные библиотеки, а в дельфи - не особо.  
 

Цитата:
Мне и 99% программистам

Не нужно творческих обобщений. Вам хватает - ок, не спорю, наверное хватает))  Мне нет, и я не понимаю причин такой нелепой убогости такой архитектуры! Если бы в дельфи стандартных коллекций хватало 99% программистов, не было бы кучи сторонних библиотек с контейнерами - DeHL, Collections, Spring, etc.
 

Цитата:
одними приписками не обойдёшься, TList хранит элементы тупо в массиве, нужно будет всё менять

Exactly! При виртуальных методах можно полностью заменить схему хранения, оставляя такой же "наружный" интерфейс. Именно для подобных вещей и нужны виртуальные методы: кастомизация!  
 
AlekXL
valgreesh

Цитата:
Оно правильно не работает.  

 
Нет, должно работать. Если не работает, то не из-за этого. Вроде бы по документации, если интерфейс (sub-interface) унаследован от другого интерфейса (parent-interface), то декларированием поддержки sub-interface мы поддерживаем и parent-interface. Более того, нужно предоставить методы реализации и для sub-  и для parent-interface.
 
A заморочка скорее всего с типом переменной-ссылкой на объект. Вместо классового типа, нужно использовать интерфейсные переменные (не TRequest, а IRequest) для получения доступа к методам интерфейса. Хз. ЛУчше привести полный код - так будет понятнее.

Всего записей: 857 | Зарегистр. 09-10-2003 | Отправлено: 17:03 14-06-2013
Eternal_Shield

Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
deks

Цитата:
with matching obj := TButton(Sender) do obj.Caption := 'ok';

Интересная конструкция. Немного запись страшновата, но ничего Подробнее... ... не знаю, я пытался на кислороде писать. Не пошло. Ну не чувствую я в нём дух Delphi. Сплошной C# с begin..end.  
 
Месяц игрался и бросил это чудо. По мне уж так лучше на С# писать, чем на кислороде. Если натив, то Delphi-only.
 

Всего записей: 767 | Зарегистр. 18-05-2009 | Отправлено: 17:45 14-06-2013 | Исправлено: Eternal_Shield, 17:46 14-06-2013
valgreesh



Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
deks

Цитата:
Нет, должно работать.

Не работает и не должно. Учим матчасть.
 
Добавлено:
Eternal_Shield

Цитата:
Ну не чувствую я в нём дух Delphi. Сплошной C# с begin..end

Абсолютно те же ощущения...

Всего записей: 292 | Зарегистр. 30-11-2011 | Отправлено: 18:05 14-06-2013
Arioch1



Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

Цитата:
В Oxygene обнаружилась для похожих вариантов две конструкции

а в них можно явно добавить else-секцию ?
 
Добавлено:

Цитата:
В обоих случаях каст T() дает nil при невозможности каста.  

 
только в этих случаях (тогда это может разрушать целостность языка) или всегда (тогда это чревато ошибками, типа типичного в ява-программах NullReferenceException )
 
Добавлено:

Цитата:
> тайпкаст, централизованный в начале функции как absolute  
 Не ясно что имеется ввиду вообще. Разговор за begin инициализатор в методе чтоли?

 
Разговор за то, что бегло просматривая два десятка функция я сразу по заголовку вижу ту, в которой используется потенциально проблемная вещь - тайпкаст - и я по одному заголовку функции вижу, что к ней надо присмотреться с особым вниманием.
 

Цитата:
Обобщенный тип:

Интересно, насколько это отличается по сути тот dyna-cast в C++ Builder
 
Можно немного по другому.
 

Код:
 
type  
   TCast = record  
       function Check<T: class>(Src: TObject; out Dst: T): Boolean; static; inline;  
   end;  
   
 ....  
   
 class function TCast.Check<T>(Src: TObject; out Dst: T): boolean;  
 begin  
   Result := Src is T;  
   if Result then  
     TObject(Dst) := Src;  
 end;
 
 
procedure TForm1.Button1Click(Sender: TObject);  
 var  
   btn: TButton;  
 begin  
   if TCast.Check(Sender, btn) then  
     btn.Caption := 'ok';  
 end;
 

 
Но!
1) это работает только с классами
2) все же пришлось заводить отдельную переменную с КОПИЕЙ значения. Неизящно, хотя и мелочь на современнмо железе.
3) по "заголовку" функции не видно сразу, что в ней используется тайп-каст
4) Представим, что с развитием процедуры мне стало нужно держать в btn действительно новую, независимую кнопку, а для "преобразованной" кнопки я завёл переменную btn1. Теперь мне надо найти и заменить, не пропустив и не опечатавшись, все места, где в коде используется TCast.
В случае absolute мне достаточно изменить заголовок функции - определение переменных. Т.е. одно место которое не сможет быть рассогласовано само с собой.

Всего записей: 904 | Зарегистр. 03-03-2010 | Отправлено: 18:22 14-06-2013
deks



Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
valgreesh

Цитата:
Не работает и не должно

 
Разобрался, правда не должно. Дружно говорим спасибо COM за возможность в потомке НЕ РЕАЛИЗОВЫВАТЬ методы базового интерфейса. Нелогично, но почему то так принято..

Всего записей: 857 | Зарегистр. 09-10-2003 | Отправлено: 18:57 14-06-2013
Arioch1



Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
COM - не объектное дерево. В нём нет понятия потомков.
 
Если взять какую-нибудь книжку по COM там скорее всего так и будет написано, что наследование на практике привело к запутанному коду, который не поддавался ни переработке ни отладке. Поэтому при задумывании архитектуры COM было решено убрать саму концепцию наследования и сделать каждый компонент (каждый интерфейс) самодостаточным чёрным ящиком.

Всего записей: 904 | Зарегистр. 03-03-2010 | Отправлено: 19:01 14-06-2013
deks



Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Arioch1
 
В Оксигене T() всегда дает nil если каст не удался.  
 
В случае опасений на nil reference, можно использовать colon operator. Подробнее про фичу: http://wiki.oxygenelanguage.com/en/Oxygene_by_Example_-_Colon_and_Null
 
Явно добавить секцию else нельзя.
 
Добавлено:

Цитата:
COM - не объектное дерево

 
Да я понимаю. Тогда стоило или убрать наследование интерфейсов, или при использовании COM делать предупреждения компилятора по поводу наследования.  
 
А еще лучше - ввести специальный тип com interface, который жил бы естественным образом для COM. Аналогично специальным типам строк и тп.  
 
А кому не надо платформенной зависимости - те делают на обычном interface,  который поддерживает всякое наследование (и в реализации) и все что нужно, без нелогичных выкрутасов.

Всего записей: 857 | Зарегистр. 09-10-2003 | Отправлено: 19:06 14-06-2013
RuXandr

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Arioch1,
 
я и не претендовал на изящность подхода, хотелось лишь попытаться найти решения в рамках Delphi копипасту, и связанным с этим багам...  
 
Решения из Кислорода прикольные, однако очень непривычно выглядит/не очевидно и  если нет возможности сделать else то уже не гуд.  
 
ну и напоследок, хотелось бы узнать вашего мнения по поводу такого решения:
 

Код:
 
procedure TForm1.Button1Click(Sender: TObject);  
 begin  
   if cast(Sender, TButton, var Btn) then  
     btn.Caption := 'ok';  
 end;  
 

 
где:
 
  1. cast - "шаблонная" функция, у которой тип третьего параметра равен аргументу T а сам аргумент  обьявлен как out, типа так: function cast<T>(Src: TObject; T; out Dst: T): Boolean;
  2. var Btn - inplace объявление локальной переменной (в текущем блоке т.е. в блоке if) с авто выводом типа от типа параметра функции cast.
  3. Все это происходит в несуществующем  компиляторе

Всего записей: 96 | Зарегистр. 13-10-2009 | Отправлено: 19:09 14-06-2013
Arioch1



Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

Цитата:
 кому не надо платформенной зависимости - те делают на обычном interface,  который поддерживает всякое наследование

Об этом плакали столько, сколько сами интерфейсы были.  
Поздно уже надеяться 15 лет спустя.
 
И если честно, никто не пробовал вносить этот отдельный тип. Смешивать объекты и интерфейсы и так не всегда просто, а новичкам просто крышу рвёт.
Представь Delphi построенную на трёх типах: классы, интерфейсы и компоненты (COM-интерфейсы). Не получилось ли бы еще хуже на практике ? уже не узнать.
 
Добавлено:

Цитата:
В случае опасений на nil reference, можно использовать colon operator

 
очень ObjC по духу. Возьмем и вызовем какой-нибудь метод, а есть он или нету - какая разница
 
но как-то не по-Паскалевски. Одни грабли это уберёт, зато другие разложит. И не факт, что они будут лучше. больно мне это напоминает исправление оишбок абсолютным on-except-end
 
Добавлено:

Цитата:
2. var Btn - inplace объявление локальной переменной (в текущем блоке т.е. в блоке if) с авто выводом типа от типа параметра функции cast.

 
а кроме функции cast у этого какие-то еще применения будут ?
менять язык ради одной функции...
лучше уж tuples вводить
 

Код:
 procedure TForm1.Button1Click(Sender: TObject);    
  begin    
    if (const T = cast(Sender, TButton)).Result then    
      T.obj.Caption := 'ok';    
  end;  

 
Как-то в таком духе.

Всего записей: 904 | Зарегистр. 03-03-2010 | Отправлено: 19:14 14-06-2013
valgreesh



Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
deks

Цитата:
А еще лучше - ввести специальный тип com interface

И тем самым окончательно всех запутать... Нынешняя ситуация является хорошим компромиссом.

Всего записей: 292 | Зарегистр. 30-11-2011 | Отправлено: 20:53 14-06-2013
deks



Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Arioch1
valgreesh
 
Я имел ввиду наоборот, упростить. Проблема интерфейсов в дельфи в том, что изначально они делались под COM, но потом стали некоей самостоятельной сущностью! В результате скрестился еж с ужом)  
 
Идея была развести понятия: вот тут - реализуем COM-интерфейс, и работаем по правилам COM но только на windows. А вот тут - просто интерфейс, он для всего языка на всех платформах! Ведь реально глупо следовать поведению COM на Android?!
 
Это как со строковыми типами: никто ж не ругал дельфи за AnsiString, WideString и тп. Каждому применению - свое!)) Хочешь универсальное - юзай String, но никто не запрещает пользовать специализированный тип для своих случаев)
 
Добавлено:

Цитата:
исправление оишбок абсолютным on-except-end

 
А по мне так ок! Хочется больше контроля? Это возможно: просто нужно сделать явную проверку на nil и обработать этот случай. А если реакции то никакой нету на else? Не - как в примере с TButton? Просто делаем свое дело, если можем. Вот тогда такой синтаксис лаконичнее и вполне читаем. Я б не отказался от такого в дельфи.

Всего записей: 857 | Зарегистр. 09-10-2003 | Отправлено: 22:05 14-06-2013
Открыть новую тему     Написать ответ в эту тему

Страницы: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39

Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Вопросы по Embarcadero RAD Studio XE4


Реклама на форуме Ru.Board.

Powered by Ikonboard "v2.1.7b" © 2000 Ikonboard.com
Modified by Ru.B0ard
© Ru.B0ard 2000-2024

BitCoin: 1NGG1chHtUvrtEqjeerQCKDMUi6S6CG4iC

Рейтинг.ru