Protected new and construct – Part 1

February 15, 2010 at 10:16
filed under Dynamics AX
Tagged , ,

In this post I want to show you the use of the new() and construct() method when instantiating classes using a simple example class. This is a design that is used a lot an AX.

It is best practice to set the new method as protected (MSDN), and it is also best practice to have a construct method in your class (MSDN). So let’s see how we should implement these best practices.

Like a good recipe, a good class has a few important ingredients:
- Parm methods for variables
- A protected new method
- A static contructor
- A run method

1. ClassDeclaration

As an example, we will create a new class: KLFShowRecordInfo
The function of the class will be to display some information about a record.

class KLFShowRecordInfo
{
    Common record;
}

This class has one variable, a record. The type is Common so we can store any record in this variable.

2. Parm method

First thing is to create a parm-method for this variable (created using parmFromCD editorscript):

public Common parmRecord(Common _record = record)
{
;
    record = _record;

    return record;
}

Your code will be much cleaner and easier to debug when you use parameter methods.

3. New Method

Next, we will override the new method and make it protected:

protected void new()
{
}

Methods that are declared as protected can only be called from methods in the class and in subclasses of the class where the protected method is declared. When we want to create an instance of this class from an other class, we’ll have to call the construct method.
When calling the new() method in any other class, we would get the following compiler error:

The method is declared protected and may only be called from methods in classes derived from KLFShowRecordInfo.

4. Construct method

When using the editorscript to create a construct() method (Right click – Scripts – template – method – construct), it will look like this:

public static KLFShowRecordInfo construct()
{
    return new KLFShowRecordInfo();
}

However, I always rewrite it like like this because it is easier to extend afterwards:

public static KLFShowRecordInfo construct()
{
    KLFShowRecordInfo kLFShowRecordInfo;
    ;

    kLFShowRecordInfo = new KLFShowRecordInfo();

    return kLFShowRecordInfo;
}

Now we’ll have to modify the construct method to receive a parameter, and use the parm method to set the variable in our class:

public static KLFShowRecordInfo construct(Common _record)
{
    KLFShowRecordInfo kLFShowRecordInfo;
    ;

    kLFShowRecordInfo = new KLFShowRecordInfo();
    kLFShowRecordInfo.parmRecord(_record);

    return kLFShowRecordInfo;
}

5. Run method
All we need now is some logic to add to this class. Most of the time, I name the method ‘run’, but you can give it any name you like. The method will display the name of the table of the record you pass to it.

void run()
{
    ;
    info(tableid2name(this.parmRecord().TableId));
}

6. Test job
Next, a job to test it:

static void KLF_TestRecordInfo(Args _args)
{
    CustTable custTable;
    ;
   
    select firstonly custTable;
   
    // this will not work because the new method is protected
    // kLFShowRecordInfo = new KLFShowRecordInfo();
   
    KLFShowRecordInfo::construct(custTable).run();
}

You can see that we only need one line of code to call our class, and we don’t need a variable, which makes the code cleaner.

Output:

CustTable

Conclusion
When creating a class, start with declaring the new method as protected. This will force you to use a static construct() method. This in turn will force you to think twice about the structure of your class, and will result in cleaner/better code with a more ‘AX-y’ feel.

In part 2, I will demonstrate how this design principle helps you to maintain your code when extending functionality.

no comments

RSS / trackback

respond