Page 1 of 1
generic functions in VO dialect
Posted: Sat Oct 25, 2025 7:37 am
by wriedmann
Hi Robert,
in my VO applications, I have many calls like this:
Code: Select all
method ReceiveBroadcastMessage( symServer ) class AnAuftragEdit
do case
case symServer == #MAuftrag .and. oDCTabControl:IsCreated( #AnAuftragSubEdit1 )
oDCTabControl:GetPage( #AnAuftragSubEdit1 ):CheckMontageAuftrag()
endcase
return nil
When migrating to X#, I have to change that code to
Code: Select all
method ReceiveBroadcastMessage( symServer ) class AnAuftragEdit
do case
case symServer == #MAuftrag .and. oDCTabControl:IsCreated( #AnAuftragSubEdit1 )
#ifdef __XSHARP__
( ( AnAuftragSubEdit1 ) oDCTabControl:GetPage( #AnAuftragSubEdit1 ) ):CheckMontageAuftrag()
#else
oDCTabControl:GetPage( #AnAuftragSubEdit1 ):CheckMontageAuftrag()
#endif
endcase
return nil
My idea would now to create a method in my TabControl class like this
Code: Select all
method GetPageNative<T>( uPage as usual ) as T
local oReturn as T
oReturn := ( T ) self:GetPage( uPage )
return oReturn
but here the compiler says
Code: Select all
error XS0030: Cannot convert type 'VO.Window' to 'T'
because currently GetPage returns a VO.Window.
My question now is, if it is a good idea to build a generic function for such code pieces, and it that is possible.
I have to admit that I'm inspired by the PCallNative() function.
Wolfgang
Re: generic functions in VO dialect
Posted: Sat Oct 25, 2025 12:24 pm
by Chris
Hi Wolfgang,
In general, I think its a very good idea to use generic methods for strongly typing stuff, but I'm not sure if it's helpful in this particular case.
First of all, to make it compile, you can first cast to object:
Code: Select all
oReturn := ( T )(OBJECT) GetPage( uPage )
or you can use the ASTYPE operator and provide a constraint for your generic method, specifying what the T type can be:
Code: Select all
method GetPageNative<T>( uPage as usual ) as T where T is Window
LOCAL oReturn AS T
oReturn := GetPage( uPage ) ASTYPE T
RETURN oReturn
This will also further help the compiler to prevent you from using this method with types that do not make sense in this context. Actually the constraint version I think should also work with the simple
syntax, but it doesn't, looks like a bug.
Anyway, the above will work, but I'm not sure what you will gain from this? You will need to call the method with specifying as a generic parameter the type that will be returned (like
), so you need to know this from the code that calls this method. Then again, maybe that's exactly what you want to achieve, in which case I think your method is perfect (also from readability POV)!
Re: generic functions in VO dialect
Posted: Sat Oct 25, 2025 2:13 pm
by wriedmann
Hi Chris,
without casting the return value of the GetPage() method, the compiler complains that the class VO.Window (that is the return type) does not has a method CheckMontageAuftrag().
And personally I see a generic method as a cleaner way of typing, so
Code: Select all
( ( AnAuftragSubEdit1 ) oDCTabControl:GetPage( #AnAuftragSubEdit1 ) ):CheckMontageAuftrag()
becomes
Code: Select all
oDCTabControl:GetPageNative<AnAuftragSubEdit1>( #AnAuftragSubEdit1 ):CheckMontageAuftrag()
and first saves a few brackets, and second makes the compiler check if the method exists and if the parameter list is true.
But in theory it should be possible to write a generics method without parameter where the generic method can take the parameter from the type:
Code: Select all
oDCTabControl:GetPageNative<AnAuftragSubEdit1>():CheckMontageAuftrag()
Wolfgang
Re: generic functions in VO dialect
Posted: Sat Oct 25, 2025 10:12 pm
by Chris
Hi Wolfgang,
Ah right, you need to make the constraint a DataWindow:
Code: Select all
FUNCTION GetPageNative<T>( ) AS T WHERE T IS DataWindow
For omitting the parameter, maybe you can use something like this inside the GetPageNative() method:
Code: Select all
FOREACH oPage AS DataWindow IN <pages list>
IF oPage:GetType() == TypeOf(T)
RETURN (T)oPage
END IF
NEXT
Didn't test it, but I think it should work.
Re: generic functions in VO dialect
Posted: Sun Oct 26, 2025 5:27 am
by wriedmann
Hi Chris,
thank you very much!
I think I prefer the version without the parameter - non because it saves some typing, but because it eliminates to specify the same (or nearly same) thing two times, making it easier to avoid errors.
I have to test that, but I think this is the way to go.
Wolfgang
Re: generic functions in VO dialect
Posted: Sun Oct 26, 2025 5:43 am
by wriedmann
Hi Chris,
it is strange: the method code
Code: Select all
method GetPageNative<T>() as T where T is VO.DataWindow
local oReturn as T
local cPageName as string
cPageName := T:GetType():Name
oReturn := self:GetPage( cPageName ) astype T
return oReturn
seems to be seen as Clipper method.
Code: Select all
error XS9126: Type 'DynamicTabControl' cannot have an overloaded method 'GetPageNative' because one of the overloads has the CLIPPER calling convention.
Adding a pascal or strict keyword does not work either
Code: Select all
method GetPageNative<T>() as T where T is VO.DataWindow pascal
nor
Code: Select all
method GetPageNative<T>() as T pascal where T is VO.DataWindow
works, returning different errors.
Wolfgang
Re: generic functions in VO dialect
Posted: Sun Oct 26, 2025 7:44 am
by Chris
Hi Wolfgang,
This happens because I assume you have enabled /vo5. The STRICT clause needs to be put at the end of the definition (after the WHERE clause), what errors are you getting when you do that?
Also do you need to indeed define multiple methods with the same name?