I am trying to use the below Pascal code in Oxygene, but it is failing to compile. The idea is to have a base generic class OTArrayList, from which a number of specialized classes descend (Boolean, LongInt, Object, etc). TEqualFunction allows for each child class to determine equalness of two elements (in the case of Boolean, with a simple operator).
A few minor syntactical changes are required, as reflected in the Oxygene code in the second code block below. (Note, this is obviously a reduced version of the actual code - this should contain everything relevant to the issue, though).
Pascal:
TYPE
GENERIC OTArrayList<T> = OBJECT(TObject)
TYPE
TEqualFunction = FUNCTION (item1, item2: T;
options: LONGINT): BOOLEAN;
VAR
fEqualFunc: TEqualFunction;
CONSTRUCTOR Create (equalFunc: TEqualFunction);
END;
TBooleanArray = OBJECT(specialize OTArrayList<BOOLEAN>)
CONSTRUCTOR Create;
END;
...
CONSTRUCTOR OTArrayList.Create (equalFunc: TEqualFunction);
BEGIN
fEqualFunc := equalFunc;
END;
{--- TBooleanArray ---}
FUNCTION OTEqualBools (item1, item2: BOOLEAN; options: LONGINT): BOOLEAN; INLINE;
BEGIN
OTEqualBools := (item1 = item2);
END;
CONSTRUCTOR TBooleanArray.Create;
BEGIN
INHERITED Create(OTEqualBools);
END;
Oxygene:
TYPE
OTArrayList<T> = PUBLIC CLASS(TObject)
TYPE
TEqualFunction = FUNCTION (item1, item2: T;
options: LONGINT): BOOLEAN;
VAR
fEqualFunc: TEqualFunction;
CONSTRUCTOR (equalFunc: TEqualFunction);
END;
TBooleanArray = PUBLIC CLASS(OTArrayList<BOOLEAN>)
CONSTRUCTOR;
END;
...
CONSTRUCTOR OTArrayList<T> (equalFunc: TEqualFunction);
BEGIN
fEqualFunc := equalFunc;
END;
{--- TBooleanArray ---}
FUNCTION OTEqualBools (item1, item2: BOOLEAN; options: LONGINT): BOOLEAN;
BEGIN
EXIT (item1 = item2);
END;
CONSTRUCTOR TBooleanArray;
BEGIN
INHERITED Create(OTEqualBools);
END;
Attempting to compile the Oxygene code gives this error: (E397) No overloaded global function “OTEqualBools” with 0 parameters in namespace…
Does Oxygene allow procedural types like this? If not, is there a way to accomplish this using an anonymous function or another approach?
Thanks Carlo. I thought that originally but get this error:
(E407) No overloaded constructor with these parameters for type “OTArrayList”, best matching overload is "constructor (equalFunc: OTArrayList.TEqualFunction)"
Sure. Only a couple minor changes from what I posted above, but this exact code compiles on my machine if I change @OTEqualBools to NIL as noted in the code. As it stands, I get this compile error:
(E486) Parameter 1 is “<method pointer>”, should be “OTArrayList.TEqualFunction”, in call to constructor OTArrayList(equalFunc: OTArrayList.TEqualFunction)"
INTERFACE
USES
java.util;
{------------------ Data Array Types -----------------}
TYPE
OTArrayList<T> = PUBLIC CLASS(Object)
TYPE
TEqualFunction = FUNCTION (item1, item2: T;
options: LONGINT): BOOLEAN;
VAR
fEqualFunc: TEqualFunction;
CONSTRUCTOR (equalFunc: TEqualFunction);
END;
TBooleanArray = PUBLIC CLASS(OTArrayList<BOOLEAN>)
CONSTRUCTOR;
END;
IMPLEMENTATION
{------------------ Generic OTArrayList implementation -----------------}
CONSTRUCTOR OTArrayList<T> (equalFunc: TEqualFunction);
BEGIN
fEqualFunc := equalFunc;
END;
{--- TBooleanArray ---}
FUNCTION OTEqualBools (item1, item2: BOOLEAN; options: LONGINT): BOOLEAN;
BEGIN
EXIT (item1 = item2);
END;
CONSTRUCTOR TBooleanArray;
BEGIN
INHERITED Create(@OTEqualBools); { Note: Changing the parameter to NIL compiles succesfully }
END;
END.
I should also note, I’m compiling with RemObjects Elements 9.3.103.2211. I’ve tried updating, but attempting to compile my project on the latest compiler version gives me over 10,000 compile errors. I’m planning to work through that soon so I can update to the latest compiler, but for now 9.3.103.2211 is working for us.
Ah yes. the problem stems from how Java does generics.
type
TEqualFunction = FUNCTION (item1, item2: T;options: LONGINT): BOOLEAN;
OTArrayList<BOOLEAN>
FUNCTION OTEqualBools (item1, item2: BOOLEAN; options: LONGINT): BOOLEAN;
In Java, generics are erased, which means that it has some compiler info that the parameters item, item2 are T, but for the runtime it’s Object.
What we do is when you pass Boolean, is that it really matches nullable Boolean, which is an object, not a value type, so it wants it as nullable boolean.
I’m going to log a bug to fix this. As a workaround you can use nullable boolean for now in the OTEqualsBool.
Thanks for the workaround, it seems to be working correctly. Out of curiosity, does nullable signal for the compiler to treat the boolean as a java.lang.boolean object rather than as the boolean primitive?