How to pass a method function to another Object? Is such a thing possible in Delphi?
For example, I am trying to create a PopupMenu in a DataModule, since this PopupMenu will be used in multiple places in the application.
The PopupMenu will use a particular function for example: GetCustomer() which returns TCustomer, on which various actions can be performed.
Each Form/Frame that is creating and using the DataModule, will want to pass it a custom implementation of GetCustomer().
I was wanting to write something like this:
TGetCustomerFunc = function: TCustomer of object;
and then create a field/property on the DataModule:
TPopupDataModule = class(TDataModule)
public
{ Public declarations }
GetCustomer: TGetCustomerFunc;
end;
GetCustomer would be assigned a method by each frame that is creating the PopupDataModule, with its own particular implementation.
However, function: TCustomer of object; is not valid syntax.
Any suggestions on how to go about this?
Your initial question: How to pass a method function to another Object?
You can declare a type for your function or procedure prototype and then pass that around as you would any other variable. Look at the use of TNotifyEvent all over the RTL, VCL and FMX for examples of how to do that.
Is such a thing possible? Yes.
It's not clear to me exactly what your use case is, and so I'm not sure of the best example to give you. You say that you want to use a TDataModule to create a TPopupMenu, which seems clear enough, but you then state that the TCustomer needs to be provided by TFrame and TForm objects that call it.
Why not just pass it the TCustomer object? It seems a bit convoluted to pass a function to get an object instead.
If I have understood what you are looking for you will want something like this:
interface
type
TCustomer = class(TObject);
TGetCustomerFunc = function(): TCustomer of Object;
TPopupDataModule = class(TDataModule)
public
function BuildPopupMenu(fnGetCustomer: TGetCustomerFunc): TPopupMenu;
...
end;
implementation
function TPopupDataModule.BuildPopupMenu(fnGetCustomer: TGetCustomerFunc): TPopupMenu;
var
pCustomer: TCustomer;
begin
if(Assigned(fnGetCustomer)) then
begin
pCustomer:=fnGetCustomer();
...
end;
end;
To call it you can then pass the address of a function in the object that's calling it. So if you define in your form:
protected
function GetTheCustomer(): TCustomer;
You can pass this routine to the TPopupDataModule like this:
{ pPopupDM:=TPopupDataModule.Create(Application); // called previously }
pPopupDM.BuildPopupMenu(Self.GetTheCustomer); // in a Form method Self is the form
Related
How can I pass property getter to a function that accepts function type?
Here is an example of what I want achieve:
class Test {
val test: String
get() = "lol"
fun testFun(func: ()->String) {
// invoke it here
}
fun callTest() {
testFun(test::get)
// error: Type mismatch: inferred type is
// KFunction1<#ParameterName Int, Char> but () -> String was expected
}
}
Is there a way?
You can reference the getter by writing ::test (or this::test).
When you write test::get, you are actually referencing the get method on String. That method takes an index and returns the character at that index.
If the property was a var and you want a reference to its setter, you can write ::test::set.
For more info on property references, see here: https://kotlinlang.org/docs/reference/reflection.html#bound-function-and-property-references-since-11
As already mentioned, you can use this::test to refer to the getter. Alternatively, if you have kotlin-reflect, you can do this::test.getter.
When you pass the field as a function, it assumes you mean the getter. As a result, if you want the setter, you have two options:
this::test::set
or
this::test.setter
The latter, just like this::test.getter requires kotlin-reflect, or the program will crash (tested locally with Kotlin 1.2.50)
You can, however, get the getter in another way. But I recommend you just stick with this::test because it's shorter.
You can do:
this::something::get
With just something::get it refers to the method inside the String class, which returns a char at an index. For reference, the method declaration:
public override fun get(index: Int): Char
If you don't mind, just use { test } (e.g. testFun { test }). This will exactly translate to your () -> String. The next best alternative is probably ::test (or this::test) as was already mentioned.
The second has probably only minor (negligible?) impact on performance. I did not test it myself, nor did I found any source which tells something regarding it. The reason why I say this, is how the byte code underneath looks like. Just due to this question I asked myself about the difference of the two: Is the property reference (::test) equivalent to a function accessing the property ({ test }) when passed as argument e.g. `() -> String`?
It seems that you are doing something wrong on logical level.
If you are overriding get method of a variable, then you can access it's value through this get method. Thus, why bother with test::get (which is totally different method, by the way, all you are doing is trying to access char from string), when you can just access variable by it's name?
So lots of languages have a pattern where you do something like this:
object = Create_Object().Set(1).Set(2).Set(3);
(I believe this originated in Smalltalk.) This works because the Set() method returns a reference to its receiver.
Can I do anything like this in Ada?
Approaches I've tried which don't work include:
-- doesn't work because the returned object is a read-only copy of the receiver
function Set(self: in out Object) return Object;
-- doesn't work because I can't return an access to a local variable
function Set(self: in out Object) return access Object;
-- looks like it works until I realise that it's not a method, and isn't doing
-- dynamic dispatch [*]
function Set(self: access Object) return access Object;
Can this be done?
I think a function with this profile will do the job for you:
function Set (Target : in Instance;
New_Item : in Integer) return Instance;
Having written a full package around that function declaration, I can write:
Object := Set (1).Set (2).Set (3);
Object.Show;
and get the output:
{1, 2, 3}
I've pushed the full sources to http://repositories.jacob-sparre.dk/miscellaneous-ada-2005-examples/.
Your third proposal is the correct approach, and you are in fact defining a primitive operation when you type "access" for the parameter. Here is an example, which uses two tagged types to show where dispatching occurs, and uses chaining of method calls. I have provided a procedure for convenience, as well, since otherwise you would have to use a temporary variable. I have used Create_Object, but an explicit call to "new", but that's of course the same thing. In addition, I have shown an example where Ada will not do dynamic dispatching when it knows statically the types involved. This is actually a nice features (performance-wise), even if indeed it requires care (and even experts are bitten every now and then :=)
with Utils; use Utils;
procedure Chain is
O : access Object := new Object;
C : access Child := new Child;
begin
O.Add (1).Add (2);
C.Add (3).Add (4);
end Chain;
package Utils is
type Object is tagged null record;
function Add (Self : access Object; Val : Integer) return access Object;
procedure Add (Self : access Object; Val : Integer); -- for convenience
type Child is new Object with null record;
overriding function Add (Self : access Child; Val : Integer) return access Child;
overriding procedure Add (Self : access Child; Val : Integer); -- for convenience
end Utils;
with Ada.Text_IO; use Ada.Text_IO;
package body Utils is
function Add (Self : access Object; Val : Integer) return access Object is
begin
Put_Line ("func Object.Add" & Val'Img);
Self.Add (Val); -- static call, not dynamic dispatch
return Self;
end Add;
procedure Add (Self : access Object; Val : Integer) is
begin
Put_Line ("proc Object.add" & Val'Img);
end Add;
overriding function Add (Self : access Child; Val : Integer) return access Child is
begin
Put_Line ("Child.Add" & Val'Img);
Self.Add (Val); -- static call, not dynamic dispatch
return Self;
end Add;
overriding procedure Add (Self : access Child; Val : Integer) is
begin
Put_Line ("proc Child.Add" & Val'Img);
end Add;
end Utils;
The output of this program is:
func Object.Add 1
proc Object.add 1
proc Object.add 2
Child.Add 3
proc Child.Add 3
proc Child.Add 4
Edit: As discussed in the comments, it is recommended to always use overriding to make sure the procedure is indeed overriding, not using a different profile. An access parameter does create a primitive operation.
From paragraph 18, function [formal] parameters can only use mode 'in' (read-only). So the input object does not get modified.
18 {parameter mode} The parameter mode of a formal parameter conveys the direction of information transfer with the actual parameter: in, in out, or out. Mode in is the default, and is the mode of a parameter defined by an access_definition. The formal parameters of a function, if any, shall have the mode in. [Ada 2005]
So I do not think that the language supports it as shown in other languages.
However, if you don't mind copies, we can save the result back in the object, but that's not the same as those other languages that you reference.
obj := obj.set("this").set(123).set(some_other_type);
You set "this" on a copy of 'obj' and return that copy. From that copy, we create a new copy and set 123 in that copy, which is in turn returned. Finally, that last result is copied and we set 'some_other_type' to it. That last copy is returned and we can save it in obj. Note that a well optimized implementation can avoid most if not all of those copies if the set() functions are small enough and inlined, but I would not could on it.
In retrospect, using procedures:
obj.set("this");
obj.set(123);
obj.set(some_other_type);
will do no copies at all.
I'm using lua 5.2.2 with luabind 0.9.
I'd like to be able to add additional class-methods through lua for any classes that I've bound in c++, but I'm unsure how to do it.
The problem is that luabind uses a function as the __index-metamethod for any bound classes instead of a table, so I don't see a way to access the class-methods at all.
e.g., I'm binding my classes like this:
luabind::module(lua)
[
luabind::class_<testClass>("TestClass")
.def(luabind::constructor<>())
.def("TestFunc",&TestFunc)
];
What I essentially want to do is to add a lua-function to the list of methods for this class, and be able to overwrite existing ones:
local t = tableOfClassMethods
local r = t.TestFunc -- Reference to the c++-function we've bound
t.SomeFunction = function(o) end -- New function for all objects of this class
t.TestFunc = function(o) end -- Should overwrite the c++-function of the same name
Any help would be appreciated.
You could use a luabind::object property and register it with the .property method of luabind
Something like this:
//Class
class FunctionCaller
{
public:
luabind::object Fn;
void SetFn(luabind::object NewFn)
{
Fn = NewFn;
};
luabind::object GetFn()
{
return Fn;
};
};
//Binding Code
luabind::class_<FunctionCaller>("FunctionCaller")
.def(luabind::constructor<>())
.property("Fn", &FunctionCaller::Fn, &FunctionCaller::SetFn, &FunctionCaller::GetFn)
Then you just need to call the luabind::object according to the luabind docs.
It's not exactly what you want to do but it could help you overwrite the function I think. You could bind the real function and have a property, check if the luabind::object is non-null, and call it or the native function.
I have coded the following, and am very new to c++, and it feels clumsy. I am trying to give 'spriteBatch' (a unique_Ptr) class scope. Here's the header file:
ref class CubeRenderer : public Direct3DBase
{
public:
CubeRenderer();
~CubeRenderer();
private:
std::unique_ptr<SpriteBatch> spriteBatch;
};
Then in the cpp file Constructor, this:
std::unique_ptr<SpriteBatch> sb(new SpriteBatch(m_d3dContext.Get()));
spriteBatch = std::move(sb);
It just seems clumsy the way I had to create 'sb' and move it to 'spriteBatch'. attempting to assign directly to 'spriteBatch' failed (maybe I simply don't know the proper syntax). Is there a way to avoid needing to use 'sb' & std::move?
Thank you.
The following should work fine:
spriteBatch = std::unique_ptr<SpriteBatch>(new SpriteBatch(m_d3dContext.Get()));
Alternatively, you can avoid repeating the type name with some make_unique function.
spriteBatch = make_unique<SpriteBatch>(m_d3dContext.Get());
There's also the reset member:
spriteBatch.reset(new SpriteBatch(m_d3dContext.Get()));
But, since you mention a constructor, why not just use the member initialization list?
CubeRenderer::CubeRenderer()
: spriteBatch(new SpriteBatch(m_d3dContext.Get())) {}
I'm trying to grab a method handle from within an object in MATLAB, yet something in the sort of str2func('obj.MethodName') is not working
The answer is to get a function handle as #Pablo has shown.
Note that your class should be derived from the handle class for this to work correctly (so that the object is passed by reference).
Consider the following example:
Hello.m
classdef hello < handle
properties
name = '';
end
methods
function this = hello()
this.name = 'world';
end
function say(this)
fprintf('Hello %s!\n', this.name);
end
end
end
Now we get a handle to the member function, and use it:
obj = hello(); %# create object
f = #obj.say; %# get handle to function
obj.name = 'there'; %# change object state
obj.say()
f()
The output:
Hello there!
Hello there!
However if we define it as a Value Class instead (change first line to classdef hello), the output would be different:
Hello there!
Hello world!
One could also write
fstr = 'say';
obj.(fstr)();
This has the advantage that it does not require a handle class to work if the object (obj) is modified.
Use #. The following code works for me:
f = #obj.MethodName
No other answer mimics str2func('obj.MethodName'). Actually, this one doesn't either, not exactly. But you can define an auxillary function like so:
function handle = method_handle(obj, mstr)
handle = #(varargin) obj.(mstr)(varargin{:});
end
Then method_handle(obj, 'MethodName') returns a handle to obj.MethodName. Unfortunately, you cannot pass the variable name of obj as a string - eval("obj") will be undefined in the function's scope.