2
ЕленочкаЦитата:
Тип Variant будет достаточно
Так вы оказывается сами все знаете. :) Вместо конкретного типа, например
String или
Integer, необходимо указать
Variant, вот и все.
Вот как бы вы реализовали процедуру обмена значений двух целочисленных переменных? Наверное, так:
procedure Swap(var First, Second: Integer);
var Temporary: integer;
begin
Temporary:=First;
First:=Second;
Second:=Temporary;
end;
Но можно сделать её типонезависимой:
procedure Swap(var First, Second: Variant);
var Temporary: Variant;
begin
Temporary:=First;
First:=Second;
Second:=Temporary;
end;
Допустим у вас есть массив; вы теперь можете менять в нем элементы местами. Сам массив тоже может быть независим от типов, например можно использовать обычный массив над вариантным типом или специальный вариантный (создаваемый функцией
VarArrayCreate(...)) массив (в последнем случае, кажется, неизбежно копирование массива, поэтому такую возможность я обойду стороной).
Итак, пример с массивом над вариантным типом:
var MyArray: array of Variant;
...
Swap(Myarray[i], MyArray[j]);
Когда вам говорили о возможности использования безтиповых указателей, то имели ввиду, что для обмена элементов массива местами, знать природу хранимых в них данных вовсе не нужно и достаточно скопировать память на низком уровне. Правда, для этого все-равно необходимо знать размер каждого элемента... В общем, в некоторых ситуациях так делать можно, но это не очень красиво да и не безопасно...
Здесь проще хранить указатели в связанном списке, что позволит менять элементы местами максимально эффективно. А ещё лучше использовать полиморфизм, т.е. писать логику над
TObject, хотя это все-равно не избавит от необходимости организовывать дипетчеризацию для выбора конкретного способа обработки различных типов данных. В любом случае, эти вопросы относятся уже к классическому паскалю, а не к object pascal aka delphi... :)
Фактически, и указатели вместе с дополнительной информацией о размере элементов и
Variant-переменные и другие подобные динамические подходы --- все это работает в run-time и может быть ужасно неэффективным, тормознутым (хотя не все с этим согласны, см. статейку
Ускоренная обработка данных типа Variant в Delphi). В более цивилизованных языках, вроде C++, эта проблема решается с применением т.н. шаблонов. В delphi такая возможность, как я уже говорил, недавно все-таки появилась, под именем delphi generics. А ведь раньше (до 2009 версии delphi 4w32 или до v2007 codegear rad studio 4.net) delphi-программистам приходилось в случае необходимости эмулировать поддержку шаблонов, например через директивы препроцессора. Причем препроцессор delphi тоже очень хилый и мало на что годится, поэтому обходились директивой
{$include ...} (историческое любопытство можно удовлетворить статейкой
Шаблоны в Object Pascal).
Примерчик же с использованием современных generics можно привести такой (опять обмен значений двух переменных):
type
TSwapper=class
class procedure Swap<T>(var First, Second: T)
end;
...
class procedure TSwapper.Swap<T>(var First, Second: T);
...
begin
...
end;
Использование:
var Variable1, Variable2: Integer;
...
TSwapper.Swap<Integer>(Variable1, Variable2);
В общем, примерно так... Неплохо бы было, если бы сюда зашел кто-нибудь разбирающийся в delphi, а то я уже все забыл. :)