Need a magic wand? Here are computed class properties!

The apparition of classes in the 4D development environment has made programming more modern and easier to scale. Classes allow the definition of properties, functions and also support inheritance.
In your application, you probably have a class to manage scientific or financial data. Let’s take the example of financial data. Say you have created functions to calculate taxes. If you also manage several countries, you may have used inheritance to manage the different rules. Then, you display these results in a list box, but if the user changes one of the attributes used in the formula, you have to manage this event to update the result.
With 4D v19 R3, 4D allows you to simplify this process thanks to computed properties: You can define a get and set function for your computed property, and when you add your property to a list box, everything is handled automatically by 4D. No more business logic in your UI.

HDI Computed properties

Definition and calculations

 
To explain the power of this concept, let’s make it as simple as possible, and start with a concrete example:
A “Rectangle” class contains two attributes, width and height, and could include functions like getSurface() and getPerimeter(), which could possibly be used.
 
However, wouldn’t it be better if the surface and perimeter were seen as regular properties, just like the others? Properties that can be read and possibly modified? And the other properties on which they depend could also be modified automatically. Well, now it’s possible thanks to computed properties.
 

Magic!

Here are two straightforward examples. In both cases, all attributes can be entered.

When you modify the width or height, the perimeters and surfaces are recalculated. The reverse is also true: change the surface or perimeter, and the widths and heights will vary accordingly.

blank

 
 
 
 
 
 
 
 
 
This also works within list boxes! Which can still be sorted on any column!
blank

 

Where is the magic?

In both cases, there isn’t any script behind the scenes! All the calculations are defined once for all within the Rectangle class! So here is a great benefit: if you need more forms using these attributes, you won’t need to write any code (just like above).

Let’s see how this is done!

Access to COMPUTED properties

GET

The first function, “get,” allows you to define how the property is computed. For this purpose, it must return the result of the calculation.
This function is the only one that is mandatory and determines by its mere presence the existence of the computed property and the possibility to use it.

The function gets surface is defined inside the Rectangle class.

Function get surface() -> $surface: Real
$surface:= This.width * this.height

Once the function above has been written, you can now use the surface property as a regular one!

$rect:=cs.Rectangle.new(60; 20)
$surface:=$rect.surface  // get the surface property
ALERT("The surface of this rectangle is: "+String($surface))

 

SET

The second function, “set”, if it exists, will manage the modification of a computed property. The surface change will allow recalculating the value of the width and the height of the rectangle.
 

// this function will be called when surface is modified
Function
set surface
($surface)

// keep the width-height ratio
$ratio:=This.width/This.height

This
.height:=Square root($surface/$ratio)
This.width:=Square root($surface*$ratio)

Once the functions above have been written, you can now modify the surface property as a regular one! The width and height attributes will be adjusted accordingly.

//Let's create a rectangle who's original width and height are 60x20
$rect:=cs.Rectangle.new(60; 20)
$surface:=$rect.surface  // get the surface property

ALERT("The surface of this rectangle is: "+String($surface))  // returns 120
// Let's modify the surface 
$rect.surface:=1000
// Then display the new width and height
$width:=$rect.width
$height:=$rect.height
ALERT("The rectangle is now: "+String($width)+" x "+String($height))  // returns 54.77 x 18.25

 

Queries and sorts…

Collections filled with objects of class Rectangle can be queried and sorted using computed properties!

Query sample:

myRectangles:=myRectangles.query("perimeter < 200")

OrderBy sample:

myRectangles:=myRectangles.orderBy("perimeter desc")

 

…and JSON

When you use an object with computed properties, these properties will be considered when you “stringify” it. 

$rect:=cs.Rectangle.new(30; 40)
ALERT(JSON Stringify($rect;*))

blank

Conclusion

This simple example shows that it is possible to perform complex operations, but the complexity will remain hidden.
It also gives better control over data publication according to contexts, user rights, etc., since rules can be defined within the class itself.
Welcome to a modern way of programming!
 
For more details, read this documentation.
 
 
Roland Lannuzel
• Product Owner & 4D Expert •After studying electronics, Roland went into industrial IT as a developer and consultant, building solutions for customers with a variety of databases and technologies. In the late 80’s he fell in love with 4D and has used it in writing business applications that include accounting, billing and email systems.Eventually joining the company in 1997, Roland’s valuable contributions include designing specifications, testing tools, demos as well as training and speaking to the 4D community at many conferences. He continues to actively shape the future of 4D by defining new features and database development tools.