Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.09.19;
Скачать: CL | DM;

Вниз

указатель на свойство или метод класса?   Найти похожие ветки 

 
mishanich   (2004-09-01 12:35) [0]

Доброго дня, профи.

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

Сначала краткая постановка задачи...
пишется модель фазы вещества - (далее упрощенно)
есть абстрактный класс TPhase, в нем свойство xi,

 TPhase = class
  private
sxi: tvec;
    procedure setxi(aindex: byte; newValue: double); virtual; abstract;
....
  public
    property xi[aindex: byte]: double read getxi write setxi;
....
 end;

 TipPhase = class (TPhase)
  private
    function c_ip: tvec; virtual; abstract;
    procedure setxi(aindex: byte; newValue: double); override;
...
 end;

procedure TipPhase.setxi;
begin
sxi[aindex]:=newValue;
sip:=c_ip;
end;

Все классы конкретных фаз наследуются от этих классов. Теперь я хочу сделать универсальный
класс (например, TVisPhase), занимающийся выводом разнообразной информации (полей/методов) о фазах. Т.е. скажем будет
функция RenderPhase, в которую я хочу передавать объект (конкретную фазу), функцию, которую нужно построить и свойство фазы
(например, xi - причем не само текущее значение, а "как-бы указатель на данное свойство" :)), от которого будет зависеть функция.
В общем, тут еще один момент есть - специально сделано так, чтобы при записи значения в свойство xi выполнялась еще одна функция,
рассчитывающий внутренний параметр фазы. Есть мат.методы (например, бисекция)

  tvec = array of double;
  tfunc = function: double of object far;

  trmmth = record
   f: tfunc;
   p: tvec;
   aindex: integer;
  end;

    function bisect(params: trmmth; rmin, rmax, delta: double): double;

и, соответственно, хотелось бы чтобы внутри бисекции автоматически (при передаче записи trmmth), при изменении параметра
p (внутри метода - в цикле), выполнялось присвоение свойству xi (т.е. при этом выполнялся метод setxi).
Если я делаю:

var ptr: pointer
   LPhase: TLPhase;
begin
LPhase:=TLPhase.create;
ptr:=@LPhase.xi;
end;

ничего не получается....

Может быть сама логика построения неверная?


 
wicked ©   (2004-09-01 12:50) [1]

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


 
KSergey ©   (2004-09-01 14:08) [2]

> private
>     procedure setxi(aindex: byte; newValue: double); virtual;
> abstract;

Не очень я силен, может что и недопонимаю.... А как этот метод потом перекрыть??


 
Amoeba ©   (2004-09-01 14:13) [3]

Метод должен быть в секции Protected.


 
KSergey ©   (2004-09-01 14:52) [4]

А по сути вопроса...
По-моему, указатель на свойство передать нельзя. Но вот на ф-цию - можно. Может отсюда и плясать? (указатель на GetXXX)


 
basken   (2004-09-01 18:23) [5]

Попробуй применить паттерн стратегии. Что-то на подобии вот этого.


unit Unit2;

interface

uses
 Contnrs, SysUtils;

type
 TStrategyPhaseClass = class of TStrategyPhase;

 TStrategyPhase = class(TObject)
 protected
   function GetOperation(const A, B: Integer): Real; virtual; abstract;
 public
   class procedure RegisterStrategy(StrategyClass: TStrategyPhaseClass);
   class procedure UnregisterStategy(StrategyClass: TStrategyPhaseClass);
   class function FindStrategyClass(AClassName: String): TStrategyPhaseClass;
   class function GetStrategyClass(AClassName: String): TStrategyPhaseClass;
 end;

 TRealizationPhaseMinus = class(TStrategyPhase)
 protected
   function GetOperation(const A, B: Integer): Real; override;
 end;

 TRealizationPhasePlus = class(TStrategyPhase)
 protected
   function GetOperation(const A, B: Integer): Real; override;
 end;

 TRealizationPhaseMul = class(TStrategyPhase)
 protected
   function GetOperation(const A, B: Integer): Real; override;
 end;

 TPhase = class(TObject)
 private
   FStrategy: TStrategyPhase;
   function GetStrategyType: String;
   procedure SetStrategy(const Value: TStrategyPhase);
   procedure SetStrategyType(const Value: String);
 public
   function GetOperation(const A, B: Integer): Real;
   property StrategyType: String read GetStrategyType write SetStrategyType;
   property Strategy: TStrategyPhase read FStrategy
     write SetStrategy;
 end;

implementation

var
 _Strategies: TClassList = nil;

{ TRealizationPhaseMul }

function TRealizationPhaseMul.GetOperation(const A, B: Integer): Real;
begin
 Result := A * B;
end;

{ TRealizationPhaseMinus }

function TRealizationPhaseMinus.GetOperation(const A, B: Integer): Real;
begin
 Result := A - B;
end;

{ TRealizationPhasePlus }

function TRealizationPhasePlus.GetOperation(const A, B: Integer): Real;
begin
 Result := A + B;
end;

{ TStrategyPhase }

class function TStrategyPhase.FindStrategyClass(AClassName: String): TStrategyPhaseClass;
var
 I: Integer;
begin
 if Assigned(_Strategies) then
   for I := 0 to Pred(_Strategies.Count) do
     if _Strategies.Items[I].ClassNameIs(AClassName) then begin
       Result := TStrategyPhaseClass(_Strategies.Items[I]);
       Exit;
     end;
 Result := nil;
end;

class function TStrategyPhase.GetStrategyClass(AClassName: String): TStrategyPhaseClass;
begin
 Result := FindStrategyClass(AClassName);
end;

class procedure TStrategyPhase.RegisterStrategy(
 StrategyClass: TStrategyPhaseClass);
begin
 if Assigned(_Strategies) then
   _Strategies.Add(StrategyClass);
end;

class procedure TStrategyPhase.UnregisterStategy(
 StrategyClass: TStrategyPhaseClass);
begin
 if Assigned(_Strategies) then
   _Strategies.Remove(StrategyClass);
end;

{ TPhase }

function TPhase.GetOperation(const A, B: Integer): Real;
begin
if Assigned(FStrategy) then
  Result :=  FStrategy.GetOperation(A, B)
else
  Result := -1;
end;

function TPhase.GetStrategyType: String;
begin
 if Assigned(FStrategy) then
   Result := FStrategy.ClassName
 else
   Result := "";
end;

procedure TPhase.SetStrategy(const Value: TStrategyPhase);
begin
//
end;

procedure TPhase.SetStrategyType(const Value: String);
var
 StategyClass: TStrategyPhaseClass;
 NewStrategy: TStrategyPhase;
begin
 if not AnsiSameText(StrategyType, Value) and (Value <> "") then begin
   StategyClass := TStrategyPhase.GetStrategyClass(Value);
   NewStrategy := StategyClass.Create;
   FreeAndNil(FStrategy);
   FStrategy := NewStrategy;
 end;
end;

initialization
 _Strategies := TClassList.Create;
 TStrategyPhase.RegisterStrategy(TRealizationPhasePlus);
 TStrategyPhase.RegisterStrategy(TRealizationPhaseMinus);
 TStrategyPhase.RegisterStrategy(TRealizationPhaseMul);

finalization
 TStrategyPhase.UnregisterStategy(TRealizationPhaseMul);
 TStrategyPhase.UnregisterStategy(TRealizationPhaseMinus);
 TStrategyPhase.UnregisterStategy(TRealizationPhasePlus);
 FreeAndNil(_Strategies);

end.


 
KSergey ©   (2004-09-02 07:44) [6]

> [5] basken   (01.09.04 18:23)

Ужас...
Это прикольно и красиво, но с точки зрения скорости, если сложные выражения - ой как не быстро, боюсь...


 
basken   (2004-09-02 12:07) [7]

> KSergey ©   (02.09.04 07:44) [6]
Ничего ужасного здесь нет! И бояться быстроты здесь нечего – опасения напрасны ;-).  Выполняться будет только метод конкретной реализации (в зависимости от выбранного типа). А по поводу красоты, наглядности и удобства использования согласен… :-)).  Ну а если  нужна уже очень высокая скорость то лучше на asme писать ;-)


 
KSergey ©   (2004-09-02 12:15) [8]

> [7] basken   (02.09.04 12:07)
> Выполняться будет только метод
> конкретной реализации

Да, разумеется!
Но выбор этой реализации!
Если предположить относительно простые реализации собственно действий (как в примере - +/-), но само их кол-во велико - то время выбора, по-моему, значительно превзойдет собственно время собственно выполенения операций.


 
basken   (2004-09-02 14:32) [9]


> KSergey ©   (02.09.04 12:15) [8]
> Да, разумеется!
> Но выбор этой реализации!
> Если предположить относительно простые реализации собственно
> действий (как в примере - +/-), но само их кол-во велико
> - то время выбора, по-моему, значительно превзойдет собственно
> время собственно выполенения операций.


Это один из возможных, вариантов! Конечно надо смотреть по ситуации, что и где лучше, удобнее, ..., применять. Иногда достаточно и обычной процедуры, или функции…


 
basken   (2004-09-02 14:41) [10]


> KSergey ©   (02.09.04 12:15) [8]
> Да, разумеется!
> Но выбор этой реализации!
> Если предположить относительно простые реализации собственно
> действий (как в примере - +/-), но само их кол-во велико
> - то время выбора, по-моему, значительно превзойдет собственно
> время собственно выполенения операций.


Это один из возможных, вариантов! Конечно надо смотреть по ситуации, что и где лучше применять. Иногда достаточно и обычной процедуры, или функции…


 
mishanich   (2004-09-02 15:56) [11]

Спасибо большое за ответы! Да еще какие развернутые!
Удивляюсь, что вообще кому-то не лень писать... :)

П.С. Короче я так понял, что обычным (?) способом указатель на свойство фиг получить... (я понимаю, что property read write всего-лишь синтаксическая конструкция, но думал - мало ли, вдруг знают как обойти ограничение)



Страницы: 1 вся ветка

Текущий архив: 2004.09.19;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.062 c
1-1094110477
serg128
2004-09-02 11:34
2004.09.19
Как программировать LPT/COM порт? Т.е. задача такая...


14-1093943954
ИМХО
2004-08-31 13:19
2004.09.19
Эмиграция в США или Европу


10-1039698119
Frodo
2002-12-12 16:01
2004.09.19
Создание клиентского приложения


4-1091541356
volser
2004-08-03 17:55
2004.09.19
Хуки


3-1093253685
dolmat
2004-08-23 13:34
2004.09.19
user naim passvord при загрузке приложения