Форум: "Основная";
Текущий архив: 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.042 c