Как описать свойство класса?

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Ответить
alaken
постоялец
Сообщения: 221
Зарегистрирован: 18.02.2010 08:02:13

Как описать свойство класса?

Сообщение alaken »

Всем привет

Как описать свойство класса, чтобы к нему можно было обращаться либо по индексу либо по строковому значению, по аналогии как в delphi в свойстве
ChildNodes интерфейса IXMLNode

Пример Delphi:

Код: Выделить всё

Var
XMLNode: IXMLNode;
...
begin
...
//обращение по индексу
  ShowMessage(XMLNode.ChildNodes[2].NodeName);

//обращение по строковому значению
  ShowMessage(XMLNode.ChildNodes['TagName'].NodeName);

// оба варианта работают!

end


В исходниках FPC в описании класса TDOMNodeList описано подобное поле, но оно может быть единственным, то есть к такому полю можно обратится только по индексу, как сделать как в Delphi, чтобы дополнительно можно было обращаться и по строковому значению?
Пример из FPC:

Код: Выделить всё

protected
function GetItem(index: LongWord): TDOMNode;
...
public
property Item[index: LongWord]: TDOMNode read GetItem; default;

Чтобы было понятнее, можно реализовать следующим образом:

Код: Выделить всё

protected
function GetItem(Name: WideString): TDOMNode;
...
public
property Item[Name: WideString]: TDOMNode read GetItem; default;
к такому свойству можно обращаться по строковому значению, но по индексу уже нельзя...

Буду признателен, если кто нибудь, предложит решение или объяснит как реализовать.
Maxizar
постоялец
Сообщения: 385
Зарегистрирован: 20.03.2010 18:48:14

Сообщение Maxizar »

Хм... знаете чисто самому стало интересно... думал что то хитрое, посмотрев исходники в Delphi, оказалось, что там это дело реализована, вот так:

Код: Выделить всё

    function GetNode(const IndexOrName: OleVariant): IXMLNode;

То есть через Вариантный тип, определяя который он видит, вы передали число или строку ну и вызывает ту или иную функцию...
Я практически никогда не работал в Варинтами, по этому извините...

Но знаете, я вот тут сделал через перегрузку функций, и если честно не понимаю, почему это работает, НО это реально работает вот:

Код: Выделить всё

unit Unit1; 

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

{ My1 }

My1 = class
  SL:TStringList;
  function GetValue(Index: Integer): String;
  function GetValue(Str: String): String; overload;

 //private


 //public
   property Value[Index:Integer]:String read GetValue;
   constructor Create;
   destructor Destroy; override;
 end;
var
  Form1: TForm1;

implementation

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var MyList:My1;
begin
    MyList:=My1.Create;

    //Caption:=MyList.SL.Values['FirstString'];

    //Caption:=MyList.Value[0];
    Caption:=MyList.Value['FirstString'];
    MyList.Free;
end;

{$R *.lfm}

{ My1 }

function My1.GetValue(Index: Integer): String;
begin
  Result:=SL.Values[SL.Strings[Index]];
end;

function My1.GetValue(Str: String): String;
begin
   Result:=SL.Values[Str];
end;

constructor My1.Create;
begin
  SL:= TStringList.Create;
  SL.Add('FirstString');
  SL.Values['FirstString']:='Value1';
end;

destructor My1.Destroy;
begin
  SL.Free;
  inherited Destroy;
end;

end.


Почему, компилятор не ругается Не понятно, ведь по идее свойство у нас требует Индекс, который явл-ся числом!.. так что не понятно вообще то что я сделал имеет право на жизнь или нет и можно ли так делать?... Ведь почему то все работает. Удивительно :!: :!: :!: :?:
kipar
новенький
Сообщения: 78
Зарегистрирован: 04.03.2010 11:15:54

Сообщение kipar »

В дельфи это не работает, так что похоже на баг компилятора fpc. Кстати, дельфи еще требует поставить overload перед обоими объявлениями GetValue, а не перед одним.

Имхо если уж разрешать такое поведение, то надо заставить объявить свойство два раза, ну или как-то так:

Код: Выделить всё

 property Value[Index]:String read GetValue;

А иначе получается путаница.
alaken
постоялец
Сообщения: 221
Зарегистрирован: 18.02.2010 08:02:13

Сообщение alaken »

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

С перегруженным методом и свойством, действительно интересно, возможно это одна из недокументированных особенностей.

Спасибо за подсказку.
Буду использовать вариантный тип.
Ответить