X++ Compiler Changes in Dynamics AX 2012
In Microsoft Dynamics AX 2012, we made compiler changes to make the X++ language more reliable and to prevent problems that may cause runtime errors.
1. Super() cannot Call an Abstract Method
Suppose an abstract method is implemented by a derived class. If the method in the derived class tries to call super() to reach the abstract method in the base class, the X++ compiler will report an error. For example:
// X++
class BaseClass
{
public abstract int method1()
{ }
}
class DerivedClass extends BaseClass
{
public int method1()
{
return super(); // Invalid call.
}
}
Reason for the Change
Abstract methods have no code body. Therefore any call to an abstract method is meaningless.
2. All Default Parameters are required to follow the Last Non-default
The X++ compiler rejects any method parameter signature which lists a default parameter before the last regular non-default parameter.
In the following X++ method signatures, parameter ‘i’ is a default parameter that causes both methods to fail to compile.
public void myInvalidMethod1(int i=1, int q) { } // Invalid signature
public void myInvalidMethod2(int i=1, int q, int r=8) { } // Invalid signature
Reason for the Change
It does not make sense to have non-default parameters follow default parameters. In such cases all calls to the method must provide an explicit value for the default parameter, and the parameter could never take its default. Therefore it understandable that .NET CIL does not support such cases. Starting in AX 2012 the X++ compiler no longer supports such cases either, to be compatible with CIL.
3. Methods that Override Should Match the Parent Signature
When a method in a derived class has the same name as a method in its base class, the X++ compiler requires the exact same parameter signature for the two methods. Also, both methods must have the exact same return type. Otherwise the derived class will fail to compile.
For example, in AX 2012 under AOT > Classes, the X++ abstract class SysAttribute is extended by the class SrsReportNameAttribute. Therefore an instance of SrsReportNameAttribute can be passed to a method that takes a parameter of type SysAttribute. But for overriding a method, these two types would not be considered an exact match, and the X++ compiler would not consider these two types to be the exact same kind of parameter or return type.
In the following X++ code example, the MyDerivedClasswould fail to compile:
// X++
class MyBaseClass
{
protected void getAttribute(SysAttribute _sysAttrib) { }
}
class MyDerivedClass extends MyBaseClass
{
protected void getAttribute(SrsReportNameAttribute _srsReportNameAttrib)
{ } //will not compile
}
Further, no default parameter can exactly match a non-default parameter, or vice verse. The number of parameters must also match. X++ supports method overriding, but not method overloading.
These rules also apply when a class implements an interface.
Reason for the Change
Without this new restriction enforced by the X++ compiler, these incompatibility errors would be detected only during run time. The above X++ code example would compile in AX 2009, but in AX 2012 the X++ compiler will reject this example.
4. Interface Implementation Must be Complete
An X++ class that implements an interface must provide code for all the methods of the interface. This includes any methods the interface inherits from another interface.
In the following X++ code example, BadClass fails to compile in AX 2012:
// X++
interface IF1
{
void method3();
}
interface IF2 extends IF1
{
void method4();
}
class BadClass implements IF2 // Fails to compile, is missing method3.
{
public void method4()
{ }
}
Reason for the Change
Same as for item 3 above.
5. The Same Method Name cannot be Inherited from both Base Class and Interface
Suppose a derived class both extends a base class and implements an interface. And suppose that the base class and the interface specify the same method name. The X++ compiler no longer tolerates this situation.
In the following X++ code example, the SadClass class fails to compile in AX 2012:
// X++
abstract class YourClass
{
void method5() { }
}
interface YourIF
{
void method5() { }
}
// SadClass fails to compile, because the name 'method5' is inherited twice.
class SadClass extends YourClass implements YourIF
{
public void method5()
{
info("Hello World.";)
}
}
Reason for the Change
Same as for item 3 above.
Comments
Anonymous
November 30, 2011
We want Parametric polymorphism in the next release of X++. Please!Anonymous
February 27, 2013
Good article. But why do we need to compile X++ in the first place, isn't X++ and interpreted language? I'm starting with AX and when installing on our test machine for the first time and it ask us to compile, is this really requiered or can I skip the compilation step?Anonymous
May 16, 2014
@Marc: In Microsoft Dynamics AX 2012, X++ source code is not directly interpreted. Instead, X++ source is compiled into "p-code" (also named "bytecode"), and the p-code is interpreted. The compile step cannot be skipped. An odd little exception is that an X++ job, under AOT > Jobs, can be run without being compiled first, or so it deceptively appears. In fact the system understands that it must first compile the job to p-code before then running it in interpreted mode. When .NET Framework CIL is generated from X++, the generation process inputs p-code, not source code. X++ source is run as CIL only in limited cases, such as in batch jobs and services which run on the Application Object Server (AOS) tier. Thanks.