Skip to main content
Version: v19 R8 BETA

Classes

Visão Geral

The 4D language supports the concept of classes. In a programming language, using a class allows you to define an object behaviour with associated properties and functions.

Once a user class is defined, you can instantiate objects of this class anywhere in your code. Each object is an instance of its class. A class can extend another class, and then inherits from its functions and properties (static and computed).

The class model in 4D is similar to classes in JavaScript, and based on a chain of prototypes.

For example, you could create a Person class with the following definition:

//Class: Person.4dm Class constructor($firstname : Text; $lastname : Text)
This.firstName:=$firstname
This.lastName:=$lastname Function get fullName() -> $fullName : text
$fullName:=This.firstName+" "+This.lastName Function sayHello()->$welcome : Text
$welcome:="Hello "+This.fullName

In a method, creating a "Person":

var $person : cs. Person //object of Person class  
var $hello : Text
$person:=cs. Person.new("John";"Doe")
// $person:{firstName: "John"; lastName: "Doe"; fullName: "John Doe"}
$hello:=$person.sayHello() //"Hello John Doe"

Managing classes

Class definition

A user class in 4D is defined by a specific method file (.4dm), stored in the /Project/Sources/Classes/ folder. The name of the file is the class name.

When naming classes, you should keep in mind the following rules:

  • A class name must be compliant with property naming rules.
  • Nomes de classe diferenciam minúsculas de maiúsculas.
  • Giving the same name to a class and a database table is not recommended, in order to prevent any conflict.

For example, if you want to define a class named "Polygon", you need to create the following file:

Project folder Project Sources Classes Polygon.4dm

Deleting a class

To delete an existing class, you can:

  • on your disk, remove the .4dm class file from the "Classes" folder,
  • in the 4D Explorer, select the class and click or choose Move to Trash from the contextual menu.

Using the 4D interface

Class files are automatically stored at the appropriate location when created through the 4D interface, either via the File menu or the Explorer.

File menu and toolbar

You can create a new class file for the project by selecting New > Class... in the 4D Developer File menu or from the toolbar.

You can also use the Ctrl+Shift+Alt+k shortcut.

Explorador

In the Methods page of the Explorer, classes are grouped in the Classes category.

To create a new class, you can:

  • select the Classes category and click on the button.
  • select New Class... from the action menu at the bottom of the Explorer window, or from the contexual menu of the Classes group.
  • select New > Class... from the contexual menu of the Explorer's Home page.

Class code support

In the various 4D windows (code editor, compiler, debugger, runtime explorer), class code is basically handled like a project method with some specificities:

  • In the code editor:
    • a class cannot be run
    • a class function is a code block
    • Goto definition on an object member searches for class Function declarations; for example, "$o.f()" will find "Function f".
    • Search references on class function declaration searches for the function used as object member; for example, "Function f" will find "$o.f()".
  • In the Runtime explorer and Debugger, class functions are displayed with the \<ClassName> constructor or \<ClassName>.\<FunctionName> format.

Class stores

Available classes are accessible from their class stores. Two class stores are available:

  • cs for user class store
  • 4D for built-in class store

cs

cs -> classStore

ParâmetrosTipoDescrição
classStoreobject<-User class store for the project or component

The cs command returns the user class store for the current project or component. It returns all user classes defined in the opened project or component. By default, only project ORDA classes are available.

Exemplo

You want to create a new instance of an object of myClass:

$instance:=cs.myClass.new()

4D

4D -> classStore

ParâmetrosTipoDescrição
classStoreobject<-4D class store

The 4D command returns the class store for available built-in 4D classes. It provides access to specific APIs such as CryptoKey.

Exemplo

You want to create a new key in the CryptoKey class:

$key:=4D. CryptoKey.new(New object("type";"ECDSA";"curve";"prime256v1"))

Class object

When a class is defined in the project, it is loaded in the 4D language environment. A class is an object itself, of "Class" class. A class object has the following properties and function:

  • name string
  • superclass object (null if none)
  • new() function, allowing to instantiate class objects.

In addition, a class object can reference a constructor object (optional).

A class object is a shared object and can therefore be accessed from different 4D processes simultaneously.

Inheritance

If a class inherits from another class (i.e. the Class extends keyword is used in its definition), the parent class is its superclass.

When 4D does not find a function or a property in a class, it searches it in its superclass; if not found, 4D continues searching in the superclass of the superclass, and so on until there is no more superclass (all objects inherit from the "Object" superclass).

Class keywords

Specific 4D keywords can be used in class definitions:

  • Function <Name> to define class functions of the objects.
  • Function get <Name> and Function set <Name> to define computed properties of the objects.
  • Class constructor to define static properties of the objects.
  • Class extends <ClassName> to define inheritance.

Function

Sintaxe

Function <name>({$parameterName : type; ...}){->$parameterName : type}
// code

Class functions are specific properties of the class. They are objects of the 4D. Function class.

In the class definition file, function declarations use the Function keyword, and the name of the function. The function name must be compliant with property naming rules.

Tip: Starting the function name with an underscore character ("_") will exclude the function from the autocompletion features in the 4D code editor. For example, if you declare Function _myPrivateFunction in MyClass, it will not be proposed in the code editor when you type in "cs. MyClass. ".

Immediately following the function name, parameters for the function can be declared with an assigned name and data type, including the return parameter (optional). Por exemplo:

Function computeArea($width : Integer; $height : Integer)->$area : Integer

Within a class function, the This command is used as the object instance. Por exemplo:

Function setFullname($firstname : Text; $lastname : Text)
This.firstName:=$firstname
This.lastName:=$lastname Function getFullname()->$fullname : Text
$fullname:=This.firstName+" "+Uppercase(This.lastName)

For a class function, the Current method name command returns: <ClassName>.<FunctionName>, for example "MyClass.myFunction".

In the application code, class functions are called as member methods of the object instance and can receive parameters if any. The following syntaxes are supported:

  • utilização do operador (). For example, myObject.methodName("hello")
  • use of a "4D. Function" class member method:

Thread-safety warning: If a class function is not thread-safe and called by a method with the "Can be run in preemptive process" attribute:

  • the compiler does not generate any error (which is different compared to regular methods),
  • an error is thrown by 4D only at runtime.

Parâmetros

Function parameters are declared using the parameter name and the parameter type, separated by a colon. The parameter name must be compliant with property naming rules. Multiple parameters (and types) are separated by semicolons (;).

Function add($x; $y : Variant; $z : Integer; $xy : Object)

If the type is not stated, the parameter will be defined as Variant.

The classic 4D syntax for method parameters can be used to declare class function parameters. Both syntaxes can be mixed. Por exemplo:

Function add($x : Integer)
var $2; $value : Integer
var $0 : Text
$value:=$x+$2
$0:=String($value)

Return value

You declare the return parameter (optional) by adding an arrow (->) and the return parameter definition after the input parameter(s) list, or a colon (:) and the return parameter type only. Por exemplo:

Function add($x : Variant; $y : Integer)->$result : Integer
$result:=$x+$y

You can also declare the return parameter by adding only : type and use the return expression (it will also end the function execution). Por exemplo:

Function add($x : Variant; $y : Integer): Integer
// some code
return $x+$y

Exemplo 1

// Class: Rectangle Class constructor($width : Integer; $height : Integer)
This.name:="Rectangle"
This.height:=$height
This.width:=$width

// Function definition Function getArea()->$result : Integer
$result:=(This.height)*(This.width)
// In a project method

var $rect : cs. Rectangle
var $area : Real

$rect:=cs. Rectangle.new(50;100)
$area:=$rect.getArea() //5000

Exemplo 2

This example uses the return expression:

Function getRectArea($width : Integer; $height : Integer) : Integer
If ($width > 0 && $height > 0)
return $width * $height
Else
return 0
End if

Function get and Function set

Sintaxe

Function get <name>()->$result : type
// código
Function set <name>($parameterName : type)
// code

Function get and Function set are accessors defining computed properties in the class. A computed property is a named property with a data type that masks a calculation. When a computed property value is accessed, 4D substitutes the corresponding accessor's code:

  • when the property is read, the Function get is executed,
  • when the property is written, the Function set is executed.

If the property is not accessed, the code never executes.

Computed properties are designed to handle data that do not necessary need to be kept in memory. They are usually based upon persistent properties. For example, if a class object contains as persistent property the gross price and the VAT rate, the net price could be handled by a computed property.

In the class definition file, computed property declarations use the Function get (the getter) and Function set (the setter) keywords, followed by the name of the property. The name must be compliant with property naming rules.

Function get returns a value of the property type and Function set takes a parameter of the property type. Both arguments must comply with standard function parameters.

When both functions are defined, the computed property is read-write. If only a Function get is defined, the computed property is read-only. In this case, an error is returned if the code tries to modify the property. If only a Function set is defined, 4D returns undefined when the property is read.

The type of the computed property is defined by the $return type declaration of the getter. It can be of any valid property type.

Assigning undefined to an object property clears its value while preserving its type. In order to do that, the Function get is first called to retrieve the value type, then the Function set is called with an empty value of that type.

Exemplo 1

//Class: Person.4dm Class constructor($firstname : Text; $lastname : Text)
This.firstName:=$firstname
This.lastName:=$lastname Function get fullName() -> $fullName : Text
$fullName:=This.firstName+" "+This.lastName Function set fullName( $fullName : Text )
$p:=Position(" "; $fullName)
This.firstName:=Substring($fullName; 1; $p-1)
This.lastName:=Substring($fullName; $p+1)
//in a project method
$fullName:=$person.fullName // Function get fullName() is called
$person.fullName:="John Smith" // Function set fullName() is called

Exemplo 2

Function get fullAddress()->$result : Object

$result:=New object

$result.fullName:=This.fullName
$result.address:=This.address
$result.zipCode:=This.zipCode
$result.city:=This.city
$result.state:=This.state
$result.country:=This.country

Class Constructor

Sintaxe

// Class: MyClass Class Constructor({$parameterName : type; ...})
// code
// code

A class constructor function, which can accept parameters, can be used to define a user class.

In that case, when you call the new() function, the class constructor is called with the parameters optionally passed to the new() function.

For a class constructor function, the Current method name command returns: <ClassName>:constructor, for example "MyClass:constructor".

Exemplo

// Class: MyClass
// Class constructor of MyClass Class Constructor ($name : Text)
This.name:=$name
// In a project method
// You can instantiate an object
var $o : cs. MyClass
$o:=cs. MyClass.new("HelloWorld")
// $o = {"name":"HelloWorld"}

Class extends <ClassName>

Sintaxe

// Class: ChildClass Class extends <ParentClass>

The Class extends keyword is used in class declaration to create a user class which is a child of another user class. The child class inherits all functions of the parent class.

Class extension must respect the following rules:

  • A user class cannot extend a built-in class (except 4D.Object and ORDA classes which are extended by default for user classes).
  • A user class cannot extend a user class from another project or component.
  • A user class cannot extend itself.
  • It is not possible to extend classes in a circular way (i.e. "a" extends "b" that extends "a").

Breaking such a rule is not detected by the code editor or the interpreter, only the compiler and check syntax will throw an error in this case.

An extended class can call the constructor of its parent class using the Super command.

Exemplo

This example creates a class called Square from a class called Polygon.

//Class: Square

//path: Classes/Square.4dm Class extends Polygon Class constructor ($side : Integer)

// It calls the parent class's constructor with lengths
// provided for the Polygon's width and height
Super($side;$side)
// In derived classes, Super must be called before you
// can use 'This'
This.name:="Square"



Function getArea()
C_LONGINT($0)
$0:=This.height*This.width

Super

Sintaxe

Super {( param{;...;paramN} )} {-> Object}
ParâmetrosTipoDescrição
parammisto->Parameter(s) to pass to the parent constructor
Resultadosobject<-Object's parent

The Super keyword allows calls to the superclass, i.e. the parent class.

Super serves two different purposes:

  1. Inside a constructor code, Super is a command that allows to call the constructor of the superclass. When used in a constructor, the Super command appears alone and must be used before the This keyword is used.
  • If all class constructors in the inheritance tree are not properly called, error -10748 is generated. It's 4D developer to make sure calls are valid.
  • If the This command is called on an object whose superclasses have not been constructed, error -10743 is generated.
  • If Super is called out of an object scope, or on an object whose superclass constructor has already been called, error -10746 is generated.
// inside myClass constructor
var $text1; $text2 : Text Super($text1) //calls superclass constructor with a text param This.param:=$text2 // use second param
  1. Inside a class member function, Super designates the prototype of the superclass and allows to call a function of the superclass hierarchy.
Super.doSomething(42) //calls "doSomething" function  
//declared in superclasses

Exemplo 1

This example illustrates the use of Super in a class constructor. The command is called to avoid duplicating the constructor parts that are common between Rectangle and Square classes.

// Class: Rectangle Class constructor($width : Integer; $height : Integer)
This.name:="Rectangle"
This.height:=$height
This.width:=$width Function sayName()
ALERT("Hi, I am a "+This.name+".")

// Function definition

Function getArea()
var $0 : Integer

$0:=(This.height)*(This.width)
//Class: Square Class extends Rectangle Class constructor ($side : Integer)

// It calls the parent class's constructor with lengths
// provided for the Rectangle's width and height
Super($side;$side)
// In derived classes, Super must be called before you
// can use 'This'
This.name:="Square" Function getArea()
C_LONGINT($0)
$0:=This.height*This.width

Exemplo 2

This example illustrates the use of Super in a class member method. You created the Rectangle class with a function:

//Class: Rectangle Function nbSides()
var $0 : Text
$0:="I have 4 sides"

You also created the Square class with a function calling the superclass function:

//Class: Square Class extends Rectangle Function description()
var $0 : Text
$0:=Super.nbSides()+" which are all equal"

Then you can write in a project method:

var $square : Object
var $message : Text
$square:=cs. Square.new()
$message:=$square.description() //I have 4 sides which are all equal

This

Sintaxe

This -> Object
ParâmetrosTipoDescrição
Resultadosobject<-Current object

The This keyword returns a reference to the currently processed object. In 4D, it can be used in different contexts.

In most cases, the value of This is determined by how a function is called. It can't be set by assignment during execution, and it may be different each time the function is called.

When a formula is called as a member method of an object, its This is set to the object the method is called on. Por exemplo:

$o:=New object("prop";42;"f";Formula(This.prop))
$val:=$o.f() //42

When a class constructor function is used (with the new() function), its This is bound to the new object being constructed.

//Class: ob Class Constructor  

// Create properties on This as
// desired by assigning to them
This.a:=42
// num método 4D  
$o:=cs.ob.new()
$val:=$o.a //42

When calling the superclass constructor in a constructor using the Super keyword, keep in mind that This must not be called before the superclass constructor, otherwise an error is generated. See this example.

In any cases, This refers to the object the method was called on, as if the method were on the object.

//Class: ob Function f()
$0:=This.a+This.b

Then you can write in a project method:

$o:=cs.ob.new()
$o.a:=5
$o.b:=3
$val:=$o.f() //8

In this example, the object assigned to the variable $o doesn't have its own f property, it inherits it from its class. Since f is called as a method of $o, its This refers to $o.

Class commands

Several commands of the 4D language allows you to handle class features.

OB Class

OB Class ( object ) -> Object | Null

OB Class returns the class of the object passed in parameter.

OB Instance of

OB Instance of ( object ; class ) -> Boolean

OB Instance of returns true if object belongs to class or to one of its inherited classes, and false otherwise.