Page 1 of 1

Method options *CONSTRUCTOR and *REQUIRED

Posted: Thu Nov 28, 2019 4:15 am
by MarcusLancaster
Hi all.

Has anybody got an example which demonstrates why you would use the *REQUIRED option on a method? I've got a *CONSTRUCTOR method running... but can't see why I would need to include *REQUIRED... the documentation simply states;

"In conjunction with *Constructor. *REQUIRED specifies that a constructor method must be invoked"

I've tried to contrive a situation where a second Constructor is defined with *REQUIRED, but where I deliberately do not cause it to run... but it doesn't appear to fail or error etc... and as far as I understand it, if there is only one Constructor, then it would run anyway...

Just wondered where / why I would use it?

Cheers for now.

Marcus.

Re: Method options *CONSTRUCTOR and *REQUIRED

Posted: Fri Nov 29, 2019 9:51 am
by BrendanB
Marcus,

try creating a RP

Code: Select all


Function Options(*DIRECT)
Begin_Com Role(*EXTENDS #PRIM_OBJT)

Define_Com Class(#prim_alph) Name(#searchValue)
Define_Com Class(#prim_alph) Name(#replacementValue)

Define_Pty Name(SearchValue) Get(*Auto #searchValue) Set(*Auto #searchValue)
Define_Pty Name(ReplacementValue) Get(*Auto #replacementValue) Set(*Auto #replacementValue)

Mthroutine Name(Create) Options(*CONSTRUCTOR *REQUIRED)
Define_Map For(*INPUT) Class(#prim_alph) Name(#Key)
Define_Map For(*INPUT) Class(#prim_alph) Name(#Value)

#searchValue := #Key
#replacementValue := #Value

Endroutine

End_Com

and then try and use it like:

Code: Select all

Define_com class(#PRIM_LCOL<#SimpleClass>) name(#ClassList)

mthroutine Name(DoSomething)

#ClassList.RemoveAll

#ClassList.Insert( (*New #SimpleClass.Create('a' 'value')))
#ClassList.Insert((*New #SimpleClass))   // should fail here

endroutine

This is a contrived example, but you should get an error message when you try and *NOT* use a constructor.

Re: Method options *CONSTRUCTOR and *REQUIRED

Posted: Sat Nov 30, 2019 2:46 am
by MarcusLancaster
Hey Brendan!

Thanks for your code sample - I think the problem I had was that my assumption was that the *REQUIRED parm was related to the method, but it seems to be more related to the define_map(s). In all my tests, to keep it simple, I didn't have any define_maps.

As you indicate, if you include a DEFINE_MAP parm in the Constructor method;

Code: Select all

mthroutine umConstructor options(*CONSTRUCTOR *REQUIRED)
define_map for(*input) class(#std_text) name(#iText)
#sys_web.alert caption('Running Constructor method')
endroutine
but then DON'T specify a parm value where the component is instantiated;

Code: Select all

#ACOL_Test.Insert((*NEW #TestComponent))

you do get an error...

An instance of class name <component class> can only be created by calling the constructor marked *REQUIRED

But the message is misleading - its the missing parm which seems to be the issue, rather than the lack of a constructor. If you remove the DEFINE_MAP from the component, the syntax is good, because the *NEW syntax will find the constructor. So *REQUIRED would appear to be more about the requirement to include parms when instantiating a component... maybe the message needs changing?

Anyway - thanks again for the code, that's the clue I needed!! At least I'm getting the message now!! Much appreciated!

Cheers for now.

Marcus.

Re: Method options *CONSTRUCTOR and *REQUIRED

Posted: Mon Dec 02, 2019 9:42 am
by BrendanB
Marcus,

The thing to remember:

*New #TestComponent

is not the same as

*New #TestComponent.umConstructor

The first is the *DEFAULT* constructor, the second is the constructor that you defined.

The required flag tells VL that it cannot use the default constructor for the object.

I think the bug is that the constructor you have written should force you to declare *New #TestComponent.umConstructor