Skip to content

Commit

Permalink
acrolinx
Browse files Browse the repository at this point in the history
  • Loading branch information
RobinARH committed Aug 27, 2021
1 parent b95c4fa commit d42a5bc
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 49 deletions.
78 changes: 40 additions & 38 deletions articles/fin-ops-core/dev-itpro/dev-ref/xpp-classes-methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ A *class* is a software construct that defines the data and methods of the insta

*Variables* contain the data for the class. Every instance that is constructed from the class declaration has its own copy of the variables. These variables are known as *instance variables*.

Methods define the behavior of a class. They are the sequences of statements that operate on the data (instance variables). By default, methods are declared to operate on the instance variables of the class. These methods are known as *instance methods* or *object methods*.
Methods define the behavior of a class. They are the sequences of statements that operate on the data (instance variables). By default, methods are declared to operate on the instance variables of the class. These methods are known as *instance methods* or *object methods*.

You can declare *static methods* and *static fields*, that do not have access to *instance variables*. These are described in [X++ static classes](xpp-static-classes.md).

## Declare a class

You must use the **Add new item** dialog in Visual Studio to add a class to your project.
You must use the **Add new item** dialog in Visual Studio to add a class to your project.

1. In Server Explorer, right-click the project, and then click **Add**.
2. In the **New Item** dialog box, select **Installed > Dynamics 365 Items > Code** in the left navigation. Then select **Class**, and then enter a name for the class.
Expand Down Expand Up @@ -77,19 +77,19 @@ public static void TestLastName()

## Constructors

To create an instance of a class, you must instantiate it by using a *constructor*.
To create an instance of a class, you must instantiate it by using a *constructor*.

+ You can define only one **new** method (constructor) in a class.
+ If you do not define a constructor, a default constructor with no parameters is created automatically by the compiler.
+ You can define only one **new** method (constructor) in a class.
+ If you do not define a constructor, a default constructor with no parameters is created automatically by the compiler.
+ You can simulate a default constructor by assigning default values to the parameters in the **new** method.

The following examples defines a parameterless constructor in the **Point** class.
The following example defines a parameterless constructor in the **Point** class.

```xpp
class Point
{
// Instance variables that are public. In practice, you would probably make this protected or private
// Instance variables that are public. In practice, you would probably make this protected or private
// and create accessor methods.
public real x = 0.0;
public real y = 0.0;
Expand All @@ -102,7 +102,7 @@ class Point
Following is information about how to create a clean inheritance model and minimize problems when code is upgraded:

+ Each class must have a single public construction method unless the class is abstract. If no initialization is required, use a static construct method. Otherwise, use a static **new** method (the default constructor for the class should be protected).
+ Each class should have at least one static **construct** method method.
+ Each class should have at least one static **construct** method.
+ Each class should have at least one static **new** method.
+ Each class should have a **new** method (the default constructor). This method should be **protected**.
+ Create accessor methods to get and set class variables.
Expand Down Expand Up @@ -170,6 +170,7 @@ Point ap = new Point();
```

## Destructors

You use a *destructor* to explicitly destroy a class instance. Instances are automatically destroyed when there are no references to them. However, you can destroy objects explicitly in the following ways:

+ Use the **finalize** method.
Expand All @@ -186,13 +187,13 @@ The following example shows the basic structure for a call to the **finalize** m
if (condition)
{
// Removes object from memory.
this.finalize();
this.finalize();
}
```

### Set reference variable to null

Set the reference variable to **null** to terminate an object. This approach destroys an object only if no other variables point to that object. You should verify that other code isn't using the variable. The following example creates an reference variable and then sets it to **null**.
Set the reference variable to **null** to terminate an object. This approach destroys an object only if no other variables point to that object. You should verify that other code isn't using the variable. The following example creates a reference variable and then sets it to **null**.

```xpp
Point myPoint = new Point();
Expand Down Expand Up @@ -230,7 +231,7 @@ info(int2Str(area));

### Static methods

Static methods, which are also known as *class methods*, belong to a class and are created by using the keyword **static**. You don't have to instantiate an object before you use static methods. Static methods are often used to work with data that is stored in tables. Member variables can't be used in a static method.
Static methods, which are also known as *class methods*, belong to a class and are created by using the keyword **static**. You don't have to instantiate an object before you use static methods. Static methods are often used to work with data that is stored in tables. Member variables can't be used in a static method.

You use the following syntax to call static methods.

Expand All @@ -257,7 +258,7 @@ Method declarations consist of a header and a body. The method header declares t

### Return type

A return type is required for each method. If a method doesn't return anything, use the **void** keyword as the return type.
A return type is required for each method. If a method doesn't return anything, use the **void** keyword as the return type.

The following example shows two methods. One method has a return type, but the other method doesn't have a return type.

Expand All @@ -276,29 +277,29 @@ int methodNameIntegerReturnValue()

### Syntax

Method declaration = *Heading* *Body* Heading = **\[** *Modifiers* **\]** *ReturnType* *MethodName* **(** *ParameterList* **)**
Method declaration = *Heading* *Body* Heading = **\[** *Modifiers* **\]** *ReturnType* *MethodName* **(** *ParameterList* **)**

Modifiers = **\[client\] \[server\] \[edit | display | public | protected | private\] \[static | abstract | final \]**
Modifiers = **\[client\] \[server\] \[edit | display | public | protected | private\] \[static | abstract | final \]**

ReturnType = *Datatype* **| void | anytype**
ReturnType = *Datatype* **| void | anytype**

MethodName = *Identifier*
MethodName = *Identifier*

ParameterList = **\[** *Parameter* **{ ,** *Parameter* **}\]**
ParameterList = **\[** *Parameter* **{ ,** *Parameter* **}\]**

Parameter = *Datatype* *Variableidentifier* **\[ =** *Expression* **\]**
Parameter = *Datatype* *Variableidentifier* **\[ =** *Expression* **\]**

Body = **{ \[** *VariableDeclarations* **\] \[** *EmbeddedFunctionDeclarations* **\] \[** *Statements* **\] }**
Body = **{ \[** *VariableDeclarations* **\] \[** *EmbeddedFunctionDeclarations* **\] \[** *Statements* **\] }**

EmbeddedFunctionDeclaration = *Heading* **{\[** *VariableDeclarations* **\] \[** *Statements* **\]}**
EmbeddedFunctionDeclaration = *Heading* **{\[** *VariableDeclarations* **\] \[** *Statements* **\]}**

If you use the **anytype** return type, the method can return any data type.

### Example of a method that doesn't have a return type

```xpp
void update ()
{
{
// Variable declared and initialized
CustTable this_Orig = this.orig();
Expand All @@ -325,20 +326,21 @@ In the following example, the **checkAccountBlocked** method returns a Boolean v
```xpp
boolean checkAccountBlocked(AmountCur amountCur)
{
if (this.blocked == CustVendorBlocked::All
||(this.blocked == CustVendorBlocked::Invoice
if (this.blocked == CustVendorBlocked::All
||(this.blocked == CustVendorBlocked::Invoice
&& amountCur > 0 ))
return checkFailed(strFmt("@SYS7987",this.accountNum));
return true;
}
```

## Method modifiers

Several modifiers can be applied to method declarations. Some of the modifiers can be combined (for example, **final static**). Here are the method modifier keywords:

+ **abstract**: The method is declared but isn't implemented in a parent class. The method must be overridden in subclasses. If you try to create an object from a subclass where one or more abstract methods that belong to the parent class haven't been overridden, you receive a compiler error.
+ **abstract**: The method is declared but isn't implemented in a parent class. The method must be overridden in subclasses. If you try to create an object from a subclass where one or more abstract methods that belong to the parent class haven't been overridden, you receive a compiler error.

Classes can also be abstract. Sometimes, a class should not be instantiated even though it represents an abstract concept. Only subclasses should be instantiated. Base classes of this type can be declared as **abstract**. For example, you want to model the concept of an account. Accounts are abstract, because only derived classes (ledger accounts and so on) exist in the real world. This examples describes a clear case where you should declare the **Account** class as **abstract**.
Classes can also be abstract. Sometimes, a class should not be instantiated even though it represents an abstract concept. Only subclasses should be instantiated. Base classes of this type can be declared as **abstract**. For example, you want to model the concept of an account. Accounts are abstract, because only derived classes (ledger accounts and so on) exist in the real world. This example describes a clear case where you should declare the **Account** class as **abstract**.
+ **display**: The method's return value should be shown on a page or a report. The value can't be modified on the page or report. Typically, the return value is a calculated value, such as a sum.
+ **edit**: The method's return type should be used to provide information for a field that is used on a page. The value in the field can be modified.
+ **final**: The method can't be overridden in any class that derives from its class.
Expand All @@ -353,9 +355,9 @@ The following examples show only the method headers.

```xpp
// A method that cannot be overridden
final int dontAlterMe()
final int dontAlterMe()
// A static method
// A static method
static void noChange()
// A display method that returns an integer
Expand Down Expand Up @@ -398,7 +400,7 @@ class Person
{
date birthDate;
// The constructor that takes a date type as a parameter.
// The constructor that takes a date type as a parameter.
// That value is assigned to the field member birthDate.
void new(date _date)
{
Expand All @@ -419,7 +421,7 @@ class Person
Person person = new Person(13\5\2010);
// Optional parameter's default is used.
Info(strFmt('Age in years today is %1 years',
Info(strFmt('Age in years today is %1 years',
real2int(person.CalculateAgeAsOfDate())));
// January 2, 2044 is the parameter value for _date.
Expand All @@ -431,7 +433,7 @@ class Person
}
```

This is an example of how you cannot skip to a second optional parameter. The **AddThreeInts** method has two optional parameters. The **callAdditions** method calls the **AddThreeInts** method. The commented out code tries to override only the **\_i3** default value, but the compiler requires that all prior optional parameters also be overridden in the call.
This is an example of how you cannot skip to a second optional parameter. The **AddThreeInts** method has two optional parameters. The **callAdditions** method calls the **AddThreeInts** method. The commented out code tries to override only the **\_i3** default value, but the compiler requires that all prior optional parameters also be overridden in the call.

```xpp
class Additions
Expand Down Expand Up @@ -461,33 +463,33 @@ Class variables are protected by default. By hiding details of the internal impl
class Point
{
// Instance variables
real x;
real x;
real y;
// Constructor to initialize to a specific or default value
void new(real _x = 10, real _y = 10)
void new(real _x = 10, real _y = 10)
{
x = _x;
y = _y;
}
// Accessor methods
void setX(real _x)
void setX(real _x)
{
x = _x;
}
void setY(real _y)
void setY(real _y)
{
y = _y;
}
real getX()
real getX()
{
return x;
}
real getY()
real getY()
{
return y;
}
Expand All @@ -514,7 +516,7 @@ A scope defines the area in which an item can be accessed. Variables that are de

## Local functions

You can declare functions inside a method. These are called local functions. While possible, it is not a best practice. Instead, you should add private methods to the class.
You can declare functions inside a method. These are called local functions. While possible, it is not a best practice. Instead, you should add private methods to the class.

+ The declarations of local functions must physically precede any non-declaration statements in the method.
+ You can declare more than one local function in your method. However, all local functions must be declared in an uninterrupted series, and the set must be terminated by one semicolon (;).
Expand Down Expand Up @@ -626,4 +628,4 @@ There is no concept of an X++ job from preview versions (AX2102 and earlier). To

The depth of the call stack is limited to 100.

[!INCLUDE[footer-include](../../../includes/footer-banner.md)]
[!INCLUDE[footer-include](../../../includes/footer-banner.md)]
2 changes: 1 addition & 1 deletion articles/fin-ops-core/dev-itpro/dev-ref/xpp-events.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ The following table shows the keywords that describe the use of delegates.

## Example

The two classes in the following code example demonstrate how to define an event, subscribe to an event, and raise an event. The **PointWithEvent** class defines a delegate, **moved**. The **move** method calls the **moved** delegate, thereby notifing any objects that have subscribed to the event. The **PointKeeper** class defines the **writeMove** method and assigns it as the event handler for the **moved** delegate of the **Point** instance created in the **createAndMove** method.
The two classes in the following code example demonstrate how to define an event, subscribe to an event, and raise an event. The **PointWithEvent** class defines a delegate, **moved**. The **move** method calls the **moved** delegate, thereby notifying any objects that have subscribed to the event. The **PointKeeper** class defines the **writeMove** method and assigns it as the event handler for the **moved** delegate of the **Point** instance created in the **createAndMove** method.

```xpp
class PointWithEvent
Expand Down
4 changes: 2 additions & 2 deletions articles/fin-ops-core/dev-itpro/dev-ref/xpp-exceptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ ms.dyn365.ops.version: AX 7.0.0

This topic describes exception handling in X++. You handle errors by using the **throw**, **try**...**catch**, **finally**, and **retry** statements to generate and handle exceptions.

An *exception* is a regulated jump away from the sequence of program execution. The instruction where program execution resumes is determined by **try**...**catch** blocks and the type of exception that is thrown. An exception is represented by a value of the **Exception** enumeration, or an instance of .NET's System.Exception class or a derived class. One exception that is often thrown is the **Exception::error** enum value. A common practice is to write diagnostic information to the Infolog before the exception is thrown.
An *exception* is a regulated jump away from the sequence of program execution. The instruction where program execution resumes is determined by `try...catch` blocks and the type of exception that is thrown. An exception is represented by a value of the **Exception** enumeration, or an instance of .NET's `System.Exception` class or a derived class. One exception that is often thrown is the **Exception::error** enum value. A common practice is to write diagnostic information to the Infolog before the exception is thrown.

The **Global::error** method is often the best way to write diagnostic information to the Infolog. For example, your method might receive an input parameter value that isn't valid. In this case, the method can throw an exception to immediately transfer control to a **catch** code block that contains logic for handling this error situation. You don't necessarily have to know the location of the **catch** block that will receive control when the exception is thrown.

Expand Down Expand Up @@ -514,6 +514,6 @@ The following table shows the exception literals that are the values of the **Ex
| UpdateConflict | An error occurred in a transaction that is using Optimistic Concurrency Control. The transaction can be retried (use a **retry** statement in the **catch** block). |
| UpdateConflictNotRecovered | An error occurred in a transaction that is using Optimistic Concurrency Control. The code won't be retried. This exception can't be caught within a transaction. |
| Warning | An exceptional event has occurred. Although the user might have to take action, the event isn't fatal. Don't throw a **warning** exception. |
| [SQL connection error X++ exception](sql-connection-error.md) | An error occured when during the query execution. The transaction will be canceled. This exception can't be caught within a transaction. |
| [SQL connection error X++ exception](sql-connection-error.md) | An error occurred when during the query execution. The transaction will be canceled. This exception can't be caught within a transaction. |

[!INCLUDE[footer-include](../../../includes/footer-banner.md)]
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ X++ is an object-oriented, application-aware, and data-aware programming languag
| Best practice checks | X++ code is checked for syntax errors during compile time. The compile process also performs best practice checks. Violations of best practices can generate compiler messages.|
| Garbage collection | The X++ runtime execution engines have automatic mechanisms to discard objects that are no longer referenced, so that memory space can be reused. |
| Interoperability | Interoperability between classes written in X++ and in C\# (or other .NET Framework languages) is supported. |
| File manipulation | File input and output is supported, including XML building and parsing. |
| File manipulation | File input and output are supported, including XML building and parsing. |
| Collections | Dynamic arrays are supported and the X++ includes several collection objects.|

## X++ compiles to Microsoft .NET CIL (Common Intermediate Language)
Expand Down
Loading

0 comments on commit d42a5bc

Please sign in to comment.