Extending class state


A new and tremendously powerful feature was introduced in the Fall Release ’16. Now you can extend class instances, including adding state. This is available for any class in the system.

 

We already know we can extend class types. Which in essence allows us to introduce new methods that consumers of the class can benefit from. That was little more than compiler magic; now we got true class extension capabilities.

Example

Suppose you want to extend the SysUserLogCleanup class. Out-of-the-box this class is deleting records from the SysUserLog table. Let’s imagine you want to archive these records to a different table before they are deleted.

The SysUserLogCleanup class is a runbase class, so you want to add a check mark to the dialog, get the result of that check box, act on it in the run method, pack/unpack etc. Here is how the state can be extended, and how to act on the dialog() and getFromDialog() methods.

[ExtensionOf(classStr(SysUserLogCleanup))]
final class mfpSysUserLogCleanup_Extension
{
    // Extending class state…
    private boolean mfpArchive;
    private DialogField mfpDialogArchive;
   
    // Adding new instance methods…
    private void mfpDialog(Dialog _dialog)
    {
        mfpDialogArchive = _dialog.addField(extendedtypestr(NoYesId), “Archive”);
        mfpDialogArchive.value(mfpArchive);
    }
    private void mfpGetFromDialog()
    {
        mfpArchive = mfpDialogArchive.value();
    }


    // Wiring up event handlers…
    [PostHandlerFor(classStr(SysUserLogCleanup), methodStr(SysUserLogCleanup, dialog))]
    public static void mfpSysUserLogCleanup_Post_Dialog(XppPrePostArgs _args)
    {
        Dialog dialog = _args.getReturnValue();
        SysUserLogCleanup instance = _args.getThis();
        instance.mfpDialog(dialog);
    }


    [PostHandlerFor(classStr(SysUserLogCleanup), methodStr(SysUserLogCleanup, getFromDialog))]
    public static void mfpSysUserLogCleanup_Post_GetFromDialog(XppPrePostArgs _args)
    {
        SysUserLogCleanup instance = _args.getThis();  
        instance.mfpGetFromDialog();
    }
}

Please notice, to be a good citizen, I applied these practices:

  • Prefixed the added members and methods. I used “mfp” as prefix. This is important to avoid name clashes with other extensions and future version of the class being extended.
  • Hooked up post-method event handlers for the methods needed.

Other interesting aspects:

  • This also work for forms.
  • This way you can add instance methods to tables – but not state. Table’s don’t have a class declaration, so that is fair.
  • This way of extending a class will not break the extended class’s encapsulation. I.e. you will not have access to any private fields or methods.

 

THIS POST IS PROVIDED AS-IS; AND CONFERS NO RIGHTS.


Comments (4)

  1. This new feature help to handle a clean code and applied best practice to reduce the impact to modified code base.

  2. Ismael says:

    This a new feature that we needed all of the time.

  3. Denis says:

    How you can then use this parameter to achieve your initial task – “want to archive these records to a different table before they are deleted”:? in any case this new parameter will not be visible in SysUserLogCleanup.run()

    1. There are multiple ways to achieve that using eventing – for example by subscribing to the SysUserLogCleanup.onDeleting event.
      I’ll continue on expanding on this example. We also need to cover pack/unpack.

Skip to main content