Показать сообщение отдельно
  #3  
Старый 23.08.2017, 06:14
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,015
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Дополню немного.
Есть 2 типа функций. Просто функции и методы класса.
Для первого варианта можно так:
Код:
type
  TFunc = function (x : double) : double;

function f1(x : double) : double;
begin
  result := x+1; // просто для примера
end;

function f2(x : double) : double;
begin
  result := x-1;
end;

function CalcFunc(x1, x2, dx : double; func : TFunc) : double;
var
  i : double;
begin
  // просто бред для примера
  result := 0;
  i := x1;
  while i <= x2 do
    begin
      result := result + func(i);
      i := i + dx;
    end;
end;

// где-то вызов
begin
  writeln('f1 ->', CalcFunc(1,5,0.2,f1);
  writeln('f2 ->', CalcFunc(1,5,0.2,f2);
end;

Для второго случая есть 2 подварианта.

а. Тоже самое, только тип описан как
Код:
type
  TFunc = function (x : double) : double of object;
тогда в основную функцию можно передавать методы любого класса.

б. Передавать объект класса. тогда их можно "нанаследовать" от одного родителя. Там есть еще вариант с мета классом.
Код:
unit Unit2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TFuncClass = class
    class function Name : String; virtual;
    class function f(x : double) : double; virtual;
  end;

  TMetaClass = class of TFuncClass;

  TF1 = class(TFuncClass)
    class function Name : String; override;
    class function f(x : double) : double; override;
  end;

  TF2 = class(TFuncClass)
    class function Name : String; override;
    class function f(x : double) : double; override;
  end;

  TForm2 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    function Calc(x1, x2, dx : double; cls : TMetaClass) : double;
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

class function TFuncClass.Name : String;
begin
  result := 'TFuncClass';
end;

class function TFuncClass.f(x : double) : double;
begin
  Raise Exception.Create('Should not be called.');
end;

class function TF1.Name : String;
begin
  result := 'f1';
end;

class function TF1.f(x : double) : double;
begin
  result := x + 1;
end;

class function TF2.Name : String;
begin
  result := 'f2';
end;

class function TF2.f(x : double) : double;
begin
  result := x - 1;
end;

function TForm2.Calc(x1, x2, dx : double; cls : TMetaClass) : double;
var
  i : double;
begin
  result := 0;
  i := x1;
  while i <= x2 do
    begin
      result := result + cls.f(i);
      i := i + dx;
    end;
end;

procedure TForm2.Button1Click(Sender: TObject);
begin
  Memo1.Lines.Add(Format('class %s, name %s -> %.4f',[TF1.ClassName,TF1.Name,Calc(1,5,0.2,TF1)]));
  Memo1.Lines.Add(Format('class %s, name %s -> %.4f',[TF2.ClassName,TF2.Name,Calc(1,5,0.2,TF2)]));
end;

end.
В результате нажатия на кнопку в Memo имеем:
Код:
class TF1, name f1 -> 78,0000
class TF2, name f2 -> 38,0000
Обрати внимание на тип TMetaClass.

ЗЫ. Я там совместил вызов собственно функции, форматирование строки и ее добавление в Memo. Думаю, разберешся.

ЗЗЫ. Для особо умных. Мне просто было интересно - помню ли я как работать с метаклассами, последний раз делал такое лет 8 назад. Что-то еще помню, написал с первого раза без ошибок.
Ответить с цитированием