OOP

Object-oriented programming (OOP)
Object-oriented programming is a programming paradigm that is supported by many programming languages including X++. In fact, there are countless examples of OOP in the standard application. OOP utilises techniques like inheritance, polymorphism and encapsulation. This strongly increases flexibility and maintainability.

OOP Concepts

 * Class
 * Object
 * Inheritance
 * Polymorphism
 * Encapsulation

Dynamics AX
In Dynamics AX, objects are usually created in the base class using a static method called ‘construct'. The construct method usually accepts parameters like table buffers or other types of variables. The construct method acts like an object factory 'producing' objects depending on the input parameters.

You might be asking yourself if isn’t it easier to put all the code in one place? That might be the case if you want to produce code in a hurry. Rest asured, this approach might be faster but it is certainly not better. The reason is simple: if code is written in an unstructured manner, finding and solving bugs is more difficult and quite often results in code that is broken in one place when fixing it in another place. This can also occur when using OOP except that it very easy to avoid if the programmer is aware of this.

This is one of the many pitfalls that OOP helps to solve. With OOP, the code pertaining to a specific purpose is encapsulated in its own class. This means maintaining the code can be done in a specific class only. If the code is changed in a class, sibling classes are not affected but children classes are. If desired, it is simple to propagate code changes to all child classes by changing the code in a single place, the base class. All child classes will automatically inherit the new code.

OO Concepts in Dynamics AX
Although Dynamics AX and X++ supports object oriented concepts, it is not full object oriented. There are serval restrictions upon each AOT element. Elements          |Inheritence|Encapsulation|Polymorphism | ---+---+-+-+ Extended Datatypes | yes      | no          | bad, ED are | |          |             | not typesave| ---+---+-+-+ Classes           | yes       | yes         | bad         | ---+---+-+-+ Tables            | no        | no          | no          | ---+---+-+-+ Forms, Reports    | no        | yes         | no          | ---+---+-+-+

Extended Datatypes have least OO support. There is something like inheritence for properties. A label defined in an upper class datatype is available in the extending datatype; Same with other properties like width and alignment, etc. Datatypes are not typesave. In fact the inheritence can be seen als Stylesheet inheritence. Thats why you need 2 fields to define a typed value on a table. Like Amount + Currency. CustAccount custAccount; VendAccount vendAccount;

custAccount = "123456"; vendAccount = custAccount; // semantic error, but syntacticall correct.

Classes in Dynamics AX support almost complete OO. In X++ you have support for single inheritance like in Java or C#. Interfaces are allowed as well, to get around multiple Inheritance. But X++ has a bug on checking the type of an object on assignment operations (Or is it a feature). The compiler allowes you to assign an object from a super class to a variable from a subclass; What may causes crashes on runtime because the super type in general has not the complete functionallity like the sub type. Example: /** Format and output table content in text file */ class PrettyPrinter {  PrettyPrinter(tableId tableNum) { ... }

public void print { ... } }

/** Output text as HTML document */ class HTMLPrettyPrinter extends PrettyPrinter {  /** Give path to a CSS file */ public void setStyleSheet(str cssFilePath) { ... } }

Usage PrettyPrinter printer; HTMLPrettyPrinter htmlPrinter = new HTMLPrettyPrinter(tableNum(InventTable));

htmlPrinter.print;   // OK printer = htmlPrinter; printer.print;       // OK, print is defined in PrettyPrinter class

printer = new PrettyPrinter(tableNum(CustTable)); htmlPrinter = printer; // Semantic error, but compiler doesn't check htmlPrinter.setStyleSheet("C:/corporate_style.css"); // Crash !

Tables have almost no support for OO concepts. Although the underlying DBMS may suppoert typed tables and inheritance, like Oracle 10g, Dynamics AX dosent. Fields are public and can be read and written directly. There is no support for get/set properties like in C#. Because there is no inheritence, there is no polymorphism. The only thing you can do is using the Common type. Every table object can be assigned to a Common variable.

There are 2 possibilies to get arround the inheritence problem. Define all subtypes as needed without having a super type. All the Journal/Line tables use this technique. The disadvantage is that there are redundant fields on every table; like a Journal Type Id. And you cannot treat similar tables with one type. The other way is to merge alle types into one big type. The only advantage is that you dont need inheritance because you have only one type. The very big disadvante is that your general purpose tabel is extremly large and filled with NULL and default values.

Forms and reports have a quite strange representation in Dynamics AX. Every form is defined as class FormRun and every report is defiend as class ReportRun. So you have hundreds FormRun and ReportRun classes in you AOT but with different names. Forms and reports dont support inheritance. If you want to have a report based on an existing one, you must duplicat it. In consequence, if the implementantion of the original report changes, you have to rework all your duplicats by hand. Same for forms. The typical pattern to get around this is to define a class with the same name, and put as much logic in it as possible. But there is no workaround for the design. Changing the design to fit the customers corporate identity is a lot of time consuming zombie work.

Examples
The FormLetter class has many child classes. SalesFormLetter and PurchFormLetter are two important ones. The FormLetter, SalesFormLetter and PurchFormLetter classes are abstract, see Abstract_classes. This means, that they cannot be instantiated directly, only child classed can be instantiated.

To use the SalesFormLetter class, call the static construct method and pass it some variables. The first variable in the construct method is a base enum DocumentStatus. This determines which object will be created and returned by the construct method.