I have a thread library which has three constructors for three different method types. I want them to be merged into one and some kind of logic to tell them apart inside the constructor. Is it possible? As there is TValue
for values and such, is there a similar thing for method types?
I have the following types supported for now;
TAgThreadMethod1 = procedure of object;
TAgThreadMethod2 = procedure;
TAgThreadMethod3 = procedure(const AThread: TAgThread) of object;
and the constructors are like so:
constructor Create(const AOnRun: TAgThreadMethod1); overload; virtual;
constructor Create(const AOnRun: TAgThreadMethod2); overload; virtual;
constructor Create(const AOnRun: TAgThreadMethod3); overload; virtual;
For reference, I don't want the user to have the ability to change the worker method at a later time after the construction at all. So if a solution exists which can do something like this in a single constructor, is also welcome;
constructor Create
(const AOnRun: [Some type which can hold arbitrary method types]);
begin
// code to identify the method contained in AOnRun.
// if supported, assign it the correct handler.
end;
The * symbol is used to pass a variable number of arguments to a function. Typically, this syntax is used to avoid the code failing when we don't know how many arguments will be sent to the function.
The two most prevalent modes of passing arguments to methods are “passing-by-value” and “passing-by-reference”.
Instead, we can call the method from the argument of another method. // pass method2 as argument to method1 public void method1(method2()); Here, the returned value from method2() is assigned as an argument to method1() . If we need to pass the actual method as an argument, we use the lambda expression.
There isn't any good way to do this, because the whole point of a method pointer is to be invoked at some later point, and you can't do that unless you know its signature. So losing the distinction between signatures is very counterproductive.
If you only want to have to store one type of call inside your object, you could make the three constructors each create an anonymous method with a unified signature that wraps calls to the three types, and just store that instead of having to deal with multiple distinct method types. But what you're asking for, specifically, won't work.
I think that the best that you can do is have a constructor that accepts the most general form of the procedural type. That is TProc<TAgThread>
. This will be the master constructor, the only virtual constructor. You can then delegate the other constructors to the master constructors.
To recap, the declaration in SysUtils
is:
type
TProc<T> = reference to procedure(Arg1: T);
So your master constructor is:
constructor Create(AOnRun: TProc<TAgThread>); overload; virtual;
The other constructors are not virtual and might look like this:
constructor Create(AOnRun: TAgThreadMethod1); overload;
Implemented as:
constructor TMyClass.Create(AOnRun: TAgThreadMethod1);
begin
Create(
procedure(Thread: TAgThread)
begin
AOnRun();
end;
);
end;
The master constructor, the virtual one, does all the work. The other constructors, the non-virtual ones, adapt their arguments to fit that of the master constructor.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With