Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как описать входной параметр процедуры многовариантно?


Страницы:   1 2

lipskiy ©   (2002-04-05 21:43:00) 

Ребята, я тут уже спрашивал, как можно описать входной параметр процедуры в мультивариантном виде, мне предложили использовать перегрузку. Но при перегрузке надо описывать два тела процедур, а если они объемные и почти одинаковые, отличаются только несколькими строчками, то описывать дважды одно и то же не хочется.

Может быть есть все-таки вариант описания входного параметра в виде списка возможных типов?
Конкретно мне нужно следующее:
proceudre Some(Input:String);
proceudre Some(Input:TStringList);
Параметр Input мне нужно описать так, чтобы при вызове ОДНОЙ процедуры Some можно было задать или String, или TStringList.
Как это сделать?


Вася Пупкин   (2002-04-06 07:29:00) [21]

2Fantasist (06.04.02 06:56)А Вы пробовали это запустить ?
Вся беда в том, что variant не может содержать ссілку на данные типа Pointer или class... боюсь, тут придется несколько больше "извращаться" :(

procedure sm(vt:TObject); overload;
var
v:variant;
begin
TVarData(v).VType:=varByRef;
TVarData(v).VPointer:=Pointer(vt);
sm(v); // здесь получите Error....
end;


Fantasist   (2002-04-06 06:56:00) [22]

Variant - вещь замечательная. Для простых типов. И перегрузка вещь замечательная. Я бы скомбинировал так:


procedure sm(vr:variant); overload;
begin
if TVarData(v).VType=varByRef then
TButton(Pointer(TVarData(vr).VPointer)).Caption:="t"
else
....
end;

procedure sm(vt:TObject); overload;
var
v:variant;
begin
TVarData(v).VType:=varByRef;
TVarData(v).VPointer:=Pointer(vt);
sm(v);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
sm(Sender);
end;


Можно еще в TVarData.Reserved1 добавить служебную информацию, что за класс. А если маленько подумать, то можно сделать переменную типа ClassId:class of TObject и распихать ее по TVarData.Reserved1 и TVarData.Reserved2 и тогда можно вообще красиво анализировать. Типа:
case classId of
TObject:
TButton:
.....


Вася Пупкин   (2002-04-06 06:50:00) [23]

либо так (это уж зависит от потребностей):

procedure TForm1.some(v:TStringList);
var i:integer;
begin
for i:=0 to V.Count-1 do some(v[i]);
end;
procedure TForm1.some(V:string);
begin
//Что-то делаем
end;


Вася Пупкин   (2002-04-06 06:39:00) [24]

А то, что два тела - так можно же сделать, например, так :
...
{ Private declarations }
procedure some(V:TStringList);reintroduce;overload;
procedure some(v:String);reintroduce;overload;
public
{ Public declarations }
end;
....
implementation

{$R *.DFM}
procedure TForm1.some(v:TStringList);
begin
// Form1.Label1.Caption:=v[0];
//Что-то делаем
end;
procedure TForm1.some(V:string);
//сделаем из string StringList
var Tmp:TStringList;
begin
Tmp:=TStringList.Create;
Tmp.Add(v);
//И вызовем перегруженную функцию для StringList
some(Tmp);
end;
при этом второе "тело" будет очень небольшим ;)


Вася Пупкин   (2002-04-06 05:44:00) [25]

Да уж...на TStringList как-то не посмотрел...
Варианты не могут быть ссылками на объекты Object Pascal. Поэтому VID © (06.04.02 01:48) "Variant не подходит... комплятор ругается " абсолютно прав.
Так что для случая
proceudre Some(Input:String);
proceudre Some(Input:TStringList);
остается либо писать "извраты" - один из вариантов -SPeller © (06.04.02 02:12)... либо использовать reintroduce ( имхо, это проще...)
Пример использования reintroduce для конкретного случая (немного усложним)
proceudre Some(Input:variant);
proceudre Some(Input:TStringList);



unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;

type
TForm1 = class(TForm)
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
procedure Some(V:variant);reintroduce;overload;
procedure Some(V:TStringList);reintroduce;overload;
public
{ Public declarations }
end;

var
Form1: TForm1;
L:TStringList;
implementation

{$R *.DFM}
procedure TForm1.Some(V:variant);
begin
Form1.Label3.Caption:=v
end;
procedure TForm1.Some(v:TStringList);
begin
Form1.Label1.Caption:=v[0];
Form1.Label2.Caption:=v[1];
end;


procedure TForm1.Button1Click(Sender: TObject);
begin
Some("123");
Some(L);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
L:=TStringList.Create;
L.Add("AAA");
L.Add("BBB");
end;

end.


SPeller   (2002-04-06 03:48:00) [26]

Можно сделать как я уже предлагал. Чтобы передать несколько строк, можно воспользоваться принципом как в ф-ции GetOpenFileName при передаче фильтров. Сделать свою ф-цию, которая выполняет всю эту рутину и передавать ей StringList, а она возвратит то, что надо. Мне кажется, это не так сложно, и выполняться оно будет быстрее, нежели обработка вариантов.


Вася Пупкин   (2002-04-06 02:24:00) [27]

SPeller © (06.04.02 02:12)Хороший вариант :)(сорьки, каламбур получился). Но не всегда годится.


SPeller   (2002-04-06 02:12:00) [28]

А если передавать в процедуру один параметр - указатель, а второй - идентификатор на что этот указатель указывает ?? И не надо никаких вариантов ?


Вася Пупкин   (2002-04-06 02:07:00) [29]

У меня не ругается :)

unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}
procedure Foo(V:variant);
begin
Form1.Label1.Caption:=v;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Foo("String");
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
Foo(123);
end;
end.


VID   (2002-04-06 01:48:00) [30]

TO Вася Пупкин: Variant не подходит... комплятор ругается :(


VID   (2002-04-06 01:46:00) [31]

можно пойти на изврат для конкретного случая:
Procedure Some (input:TStringList; IsTypeString:Boolean);
//В параметре input передаёшь список
//В параметре IsTypeString ставишь TRUE когда передаёшь строку, иначе - FALSE
begin
IF IsTypeString = true then
begin
Result := Input.Items.Strings[0]; //В этой строке списка и должно находиться нужное строковое значение
end
else
begin
Result := Input.Items.Count //В этом случае процедура работает уже как-бы со списком
end;

end;

спору нет - изврат, но сгодится :)))


Вася Пупкин   (2002-04-06 01:46:00) [32]

Или пользуй VARIANT VID © (06.04.02 01:00)


Вася Пупкин   (2002-04-06 01:44:00) [33]

Ну дык ... у тебя и получится уникальный список параметров:

type
TForm1 = class(TForm)
....
private
procedure Close(S:string);reintroduce;overload;
procedure Close(i:integer);reintroduce;overload;
procedure Close(i,j:integer);reintroduce;overload;

implementation
...
procedure TForm1.Close(S:string);
begin
....
end;

procedure TForm1.Close(i:integer);
begin
....
end;


lipskiy   (2002-04-06 01:35:00) [34]

Дык мне не надо так.
Мне надо один метод, но чтоб один из входных параметров мог быть в разных типах.


Вася Пупкин   (2002-04-06 01:31:00) [35]

Есть еще возможность (Delphi >=4)
В рамках одного класса можно иметь несколько одноименных методов.При обнаружении одноименного метода компилятор предупреждает, что у класса уже есть аналогичный метод с другими параметрами. Для подавления сообщений объявление метода можно сопровождать словом reintroduce.
Чтобы одноименные методы можно было отличить друг от друга, каждый из них должен иметь уникальный набор параметров.


lipskiy   (2002-04-06 01:26:00) [36]

Не-а, не пробовал.
Я это не умею - с variant, я его боюсь, он какой-то очень виртуальный.
Шутка.
Как это делается, ась?
Если мона - примерчик.


VID   (2002-04-06 01:00:00) [37]

а ты пробовал использовать тип VARIANT, а потом проводить проверку типа переменной, или ещё что-то в этом роде ?


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо