Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.09.19;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.029 c
1-1094041802
ShimON
2004-09-01 16:30
2004.09.19
размер Dll


1-1093960037
DimonNew
2004-08-31 17:47
2004.09.19
передача массива в процедуру


10-1039194547
Павел
2002-12-06 20:09
2004.09.19
Создание собственного маршаллера (proxy-stub) вручную


1-1094493087
lipskiy
2004-09-06 21:51
2004.09.19
Как разрешить обновляться только конкретному объекту?


14-1093677955
ASilver
2004-08-28 11:25
2004.09.19
Подскажите литературу по программированию на perl под Linux.





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский