メインコンテンツまでスキップ
バージョン: 開発中

クラス

概要

4D ランゲージでは クラス の概念がサポートされています。 プログラミング言語では、クラスを利用することによって、属性やメソッドなどを持つ特定のオブジェクト種を定義することができます。

ユーザークラスが定義されていれば、そのクラスのオブジェクトをコード内で インスタンス化 することができます。 各オブジェクトは、それ自身が属するクラスのインスタンスです。 クラスは、別のクラスを 継承 することで、その 関数 と、(宣言された および 計算された) プロパティを受け継ぐことができます。

4D におけるクラスモデルは JavaScript のクラスに類似しており、プロトタイプチェーンに基づきます。

たとえば、次のように Person クラスを定義した場合:

// クラス: 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

この "Person" のインスタンスをメソッド内で作成するには、以下のように書けます:

var $person : cs.Person // Person クラスのオブジェクト
var $hello : Text
$person:=cs.Person.new("John";"Doe")
// $person:{firstName: "John"; lastName: "Doe"; fullName: "John Doe"}
$hello:=$person.sayHello() // "Hello John Doe"

クラスの管理

クラス定義

4D においてユーザークラスとは、/Project/Sources/Classes/ フォルダーに保存された専用の メソッド ファイル (.4dm) によって定義されます。 ファイル名がクラス名になります。

クラスを命名する際には、次のルールに留意してください:

  • クラス名プロパティ名の命名規則 に準拠している必要があります。
  • クラス名の大文字・小文字は区別されます。
  • 競合防止のため、データベースのテーブルと同じ名前のクラスを作成するのは推奨されないこと

たとえば、"Polygon" という名前のクラスを定義するには、次のファイルを作成する必要があります:

Project フォルダー Project Sources Classes Polygon.4dm

クラスの削除

既存のクラスを削除するには:

  • ディスク上で "Classes" フォルダーより .4dm クラスファイルを削除します。
  • 4D エクスプローラーでは、クラスを選択した状態で をクリックするか、コンテキストメニューより 移動ゴミ箱 を選択します。

4D インターフェースの使用

ファイル メニューまたはエクスプローラーなど、4D インターフェースを介してクラスを作成した場合には、クラスファイルは自動的に適切な場所に保存されます。

ファイルメニューとツールバー

4D 開発の ファイル メニューまたはツールバーより 新規 > クラス... を選択することで、開いているプロジェクトにクラスファイルを新規作成することができます。

Ctrl+Shift+Alt+k ショートカットも使用できます。

エクスプローラー

エクスプローラーの メソッド ページにおいて、クラスは クラス カテゴリに分類されています。

クラスを新規作成するには次の方法があります:

  • クラス カテゴリを選択し、 ボタンをクリックします。
  • エクスプローラーウィンドウの下部にあるアクションメニュー、またはクラスグループのコンテキストメニューから 新規クラス... を選択します。
  • エクスプローラーのホームページのコンテキストメニューより 新規 > クラス... を選択します。

クラスのコードサポート

各種 4Dウィンドウ (コードエディター、コンパイラー、デバッガー、ランタイムエクスプローラー) において、クラスコードは "特殊なプロジェクトメソッド" のように扱われます:

  • コードエディター:
    • クラスは実行できません
    • クラスメソッドはコードのブロックです
    • オブジェクトメンバーに対する 定義に移動 操作はクラスの Function 宣言を探します。例: "$o.f()" の場合、"Function f" を見つけます。
    • クラスのメソッド宣言に対する 参照箇所を検索 操作は、そのメソッドがオブジェクトメンバーとして使われている箇所を探します。例: "Function f" の場合 "$o.f()" を見つけます。
  • ランタイムエクスプローラーおよびデバッガーにおいて、クラスメソッドは <ClassName> コンストラクターまたは <ClassName>.<FunctionName> 形式で表示されます。

クラスストア

定義されたクラスには、クラスストアよりアクセスすることができます。 クラスストアには次の二つが存在します:

  • cs - ユーザークラスストア
  • 4D - ビルトインクラスストア

cs

cs : Object

引数説明
classStoreObject&larr;プロジェクトまたはコンポーネントのユーザークラスストア

cs コマンドは、カレントプロジェクトまたはコンポーネントのユーザークラスストアを返します。 これには、プロジェクトまたはコンポーネントにて 定義 されている、すべてのユーザークラスが含まれます。 デフォルトでは、 ORDAクラス のみ利用可能です。

例題

myClass オブジェクトの新規インスタンスを作成するには、次のように書きます:

$instance:=cs.myClass.new()

4D

4D : Object

引数説明
classStoreObject&larr;4Dクラスストア

4D コマンドは、ビルトイン 4Dクラスのクラスストアを返します。 CryptoKey などの専用 API へのアクセスを提供します。

例題

CryptoKey クラスに新規キーを作成するには、次のように書きます:

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

ビルトイン4Dクラスの数を表示します:

 var $keys : collection
$keys:=OB Keys(4D)
ALERT(String($keys.length)+"件のビルトインクラスが存在します。")

Class オブジェクト

プロジェクトにおいてクラスが 定義 されていれば、それは 4Dランゲージ環境に読み込まれます。 クラスとは、それ自身が "Class" クラス のオブジェクトです。 Class オブジェクトは次のプロパティや関数を持ちます:

また、Class オブジェクトは constructor オブジェクトを参照することも可能です (任意)。

Class オブジェクトそのものは 共有オブジェクト です。 したがって、異なる 4Dプロセスから同時にアクセスすることができます。

継承

クラス宣言において Class extends キーワードを使うと、そのクラスは親クラス (つまり スーパークラス) を継承します。

関数やプロパティがクラス内で見つからない場合、4D はそのクラスの スーパークラス 内を検索します。 見つからない場合、4D はさらに、そのスーパークラスのスーパークラス内を探します。 これは、スーパークラスが存在しなくなるまで続きます (すべてのオブジェクトは "Object" スーパークラスを継承しています)。

クラスキーワード

クラス定義内では、専用の 4Dキーワードが使用できます:

  • Function <Name>: オブジェクトのクラス関数を定義します。
  • Class constructor: クラスの新規インスタンス (オブジェクト) を初期化します。
  • property: オブジェクトのスタティックプロパティを型定義します。
  • Function get <Name>Function set <Name>: オブジェクトの計算プロパティを定義します。
  • Class extends <ClassName>: 継承を定義します。
  • This and Super are commands that have special

Function

シンタックス

{shared} Function <name>({$parameterName : type; ...}){->$parameterName : type}
// コード

クラス関数とは、当該クラスのプロパティです。 クラス関数は 4D.Function クラスのオブジェクトです。 クラス定義ファイルでは、Function キーワードに続けて関数名を指定して宣言をおこないます。

共有クラス 内で関数が宣言されている場合は、shared キーワードを使用することによって、Use...End use structure 構文なしで関数を呼び出せるようにできます。 詳細については、後述の 共有関数 の項目を参照ください。

関数名は プロパティ名の命名規則 に準拠している必要があります。

プロパティと関数は同じ名前空間を共有しているため、同じクラスのプロパティと関数に同じ名前を使用することは許されていません (この場合、エラーが発生します)。

tip

アンダースコア ("_") 文字で関数名を開始すると、その関数は 4Dコードエディターの自動補完機能から除外されます。 たとえば、MyClassFunction _myPrivateFunction を宣言した場合、コードエディターにおいて "cs.MyClass." とタイプしても、この関数は候補として提示されません 。

関数名のすぐ後に、名前とデータ型を指定して 引数 を宣言します (戻り値の宣言も可)。 例:

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

クラスメソッド内でオブジェクトインスタンスを参照するには This コマンドを使います。 例:

Function setFullname($firstname : Text; $lastname : Text)
This.firstName:=$firstname
This.lastName:=$lastname

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

クラス関数の場合には、Current method name コマンドは次を返します: <ClassName>.<FunctionName> (例: "MyClass.myFunction")。

アプリケーションのコード内では、クラス関数はオブジェクトインスタンスのメンバーメソッドとして呼び出され、引数 を受け取ることができます。 以下のシンタックスがサポートされています:

  • () 演算子の使用。 例: myObject.methodName("hello")
  • "4D.Function" クラスメンバーメソッドの使用:
スレッドセーフに関する警告

クラス関数がスレッドセーフではないのに、"プリエンプティブプロセスで実行可能" なメソッドから呼び出された場合:

  • 普通のメソッドの場合とは異なり、コンパイラーはエラーを生成しません。
  • ランタイムにおいてのみ、4D はエラーを生成します。

引数

関数の引数は、引数名とデータ型をコロンで区切って宣言します。 パラメーター名は プロパティ名の命名規則 に準拠している必要があります。 複数のパラメーター (およびその型) を宣言する場合は、それらをセミコロン (;) で区切ります。

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

パラメーターの型が宣言されていない場合には、バリアント 型として定義されます。

戻り値

関数の戻り値を宣言するには (任意)、入力パラメーターリストに矢印 (->) と戻り値の定義を追加します。 例:

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

コロン (:) 記号の後に戻り値のデータ型だけを指定し、そのうえで return 文 を使って戻り値を返すこともできます (これは関数の実行を終了します)。 例:

Function add($x : Variant; $y : Integer): Integer
// なんらかのコード
return $x+$y

例題 1

property name : Text
property height; width : Integer

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

// 関数定義
Function getArea()->$result : Integer
$result:=(This.height)*(This.width)
// プロジェクトメソッドにて

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

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

例題 2

return 文 を使った例です:

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

Class Constructor

シンタックス

// クラス: MyClass
{shared} {{session} singleton} Class Constructor({$parameterName : type; ...})
// コード

クラスコンストラクター関数を使って、ユーザークラスのオブジェクトを生成・初期化することができます。 このコンストラクターは任意の 引数 を受け取ることができます。

クラスコンストラクターが定義されていると、new() 関数を呼び出したときに、当該コンストラクターが呼び出されます (コンストラクターで引数を指定している場合は new() 関数に渡します)。

コンストラクター関数は、1つのクラスに 1つしか存在できません (そうでない場合はエラーが返されます)。 Super キーワードを使用することで、コンストラクターはスーパークラス (親クラス) のコンストラクターを呼び出すことができます。

コンストラクター内でインスタンスのプロパティを作成し、型宣言することができます (例題参照)。 また、インスタンスプロパティの値が、コンストラクターに渡される引数に依存しない場合は、property キーワードを使用して定義することができます。

shared キーワードを使うと 共有クラス が作成されます。共有クラスは、共有オブジェクトのインスタンス化にのみ使われます。 詳細については、後述の 共有クラス の項目を参照ください。

singleton キーワードを使うと シングルトン が作成されます。シングルトンクラスは、クラスインスタンスを一つに限定する場合に使われます。 session singleton キーワードを使うと、セッションごとに 1つのインスタンスを作成します。 詳細については、後述の シングルトンクラス の項目を参照ください。

例題

// クラス: MyClass
// MyClass のクラスコンストラクター
Class constructor ($name : Text ; $age : Integer)
This.name:=$name
This.age:=$age
// プロジェクトメソッドにて
// オブジェクトをインスタンス化します
var $o : cs.MyClass
$o:=cs.MyClass.new("John";42)
// $o = {"name":"John";"age":42}

property

シンタックス

property <propertyName>{; <propertyName2>;...}{ : <propertyType>}

property キーワードを使用して、ユーザークラス内のプロパティを宣言することができます。 クラスプロパティには、名前と型があります。

クラスプロパティを宣言することで、コードエディターの自動補完機能とエラー検出機能を強化します。

プロパティは、new() 関数が呼び出されたときに、新規作成するオブジェクトについて宣言されますが、自動で追加されるわけではありません (値が割り当てられた場合にのみ追加されます)。

宣言と同時にプロパティを初期化 すると、そのプロパティは自動的にオブジェクトに追加されます。

プロパティ名は プロパティ名の命名規則 に準拠している必要があります。

プロパティと関数は同じ名前空間を共有しているため、同じクラスのプロパティと関数に同じ名前を使用することは許されていません (この場合、エラーが発生します)。

プロパティの型として、以下のものがサポートされています:

propertyType内容
Textテキスト値
Date日付値
Time時間値
Booleanブール値
Integer倍長整数値
Real実数値
Pointerポインター値
Pictureピクチャー値
BlobスカラーBLOB値
Collectionコレクション値
Variantバリアント値
Objectデフォルトクラス (4D.Object) のオブジェクト
4D.<className>4Dクラス名のオブジェクト
cs.<className>ユーザークラス名のオブジェクト
cs.<namespace>.<className><namespace> コンポーネントクラス名のオブジェクト

宣言時に型を省略すると、プロパティはバリアント型として作成されます。

info

property キーワードは、クラス関数内の Function および Class Constructor ブロック外でのみ使用できます。

宣言と同時にプロパティを初期化する

プロパティを宣言する際には、1つのステートメントでデータ型と初期値の両方を指定することができます。 シンタックスは次の通りです:

property <propertyName> { : <propertyType>} := <Propertyvalue>

このシンタックスを使用する場合、複数のプロパティを一度に宣言することはできません。

宣言の際には型を省略することができます。その場合、可能な限り型は推論されます。 例:

// クラス: MyClass

property name : Text := "Smith"
property age : Integer := 42

property birthDate := !1988-09-29! // 日付は推測されます
property fuzzy // バリアント

プロパティを宣言行で初期化していると、new() 関数によるインスタンス化の後、コンストラクターが呼び出される前にクラスオブジェクトにプロパティが追加されます。

もしクラスが他のクラスを 継承 する場合、親クラスのプロパティは子クラスのプロパティよりも先にインスタンス化されます。

宣言と同時に色かするプロパティが 共有クラス のオブジェクトまたはコレクションである場合、その値は自動的に共有された値に変換されます:

// 共有クラス内
property myCollection := ["something"]
// myCollection は共有コレクションとなり、
// 以下と同等です:
myCollection := New shared collection("something")

例題

// クラス: MyClass

property name : Text
property age : Integer
property color : Text := "Blue"

メソッド内で:

var $o : cs.MyClass
$o:=cs.MyClass.new() // $o:{"color" : "Blue"}
$o.name:="John" // $o:{"color" : "Blue"; "name" : "John"}
$o.age:="Smith" // シンタックスチェックでエラー

Function getFunction set

シンタックス

{shared} Function get <name>()->$result : type
// コード
{shared} Function set <name>($parameterName : type)
// コード

Function getFunction set は、クラスの 計算プロパティ を定義するアクセサーです。 計算プロパティとは、計算をマスクするデータ型を持つ命名プロパティです。 計算プロパティの値にアクセスすると、4D は対応するアクセサーのコードを実行します:

  • プロパティを読み取るときには Function get が実行されます。
  • プロパティに書き込むときには Function set が実行されます。

プロパティがアクセスされない場合は、コードも実行されません。

計算プロパティは、メモリ上に保持する必要のないデータを処理するために設計されています。 計算プロパティは通常、永続的なプロパティに基づいています。 たとえば、クラスオブジェクトの永続的なプロパティとして、税込価格消費税率 が含まれている場合、税抜価格 は計算プロパティで処理することができます。

クラス定義ファイルでは、計算プロパティの宣言には、Function get (ゲッター) と Function set (セッター) のキーワードを使い、その後にプロパティ名を記述します。 名称は プロパティ名の命名規則 に準拠している必要があります。

Function get はプロパティの型の値を返し、Function set はプロパティの型の引数を受け取ります。 どちらも、標準的な 関数の引数 のルールに準拠する必要があります。

両方の関数が定義されている場合、計算プロパティは read-write となります。 Function get のみが定義されている場合、計算プロパティは read-only です。 この場合、コードがプロパティを変更しようとするとエラーが返されます。 Function set のみが定義されている場合、4D はプロパティの読み取り時に undefined を返します。

共有クラス 内で関数が宣言されている場合は、shared キーワードを使用することによって、Use...End use 構文なしで関数を呼び出せるようにできます。 詳細については、後述の 共有関数 の項目を参照ください。

計算プロパティの型は、ゲッター$return の型宣言によって定義されます。 有効なプロパティタイプ であれば、いずれも使用可能です。

オブジェクトプロパティに undefined を代入すると、型を保持したまま値がクリアされます。 このためには、まず Function get を呼び出して値の型を取得し、次にその型の空の値で Function set を呼び出します。

例題 1

// クラス: Person.4dm
property firstName; lastName : Text

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)
// プロジェクトメソッドにて
$fullName:=$person.fullName // Function get fullName() が呼び出されます
$person.fullName:="John Smith" // Function set fullName() が呼び出されます

例題 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 extends <ClassName>

シンタックス

// Class: ChildClass
Class extends <ParentClass>

クラス宣言において Class extends キーワードを使うと、別のユーザークラスの子ユーザークラスを作成することができます。 この子クラスは、親クラスのすべての機能を継承します。

クラス継承は次のルールに沿っている必要があります:

  • ユーザークラスはビルトインクラスを継承できません (例外は 4D.Object および ORDAクラス で、すべてのユーザークラスにデフォルトで継承されます)。
  • ユーザークラスは、別のプロジェクトやコンポーネントのユーザークラスを継承できません。
  • ユーザークラスは、自身を継承することはできません。
  • 間接的にも、自身を継承することはできません (例: "a" extends "b" かつ "b" extends "a")。
  • 共有クラスでないユーザークラスを継承 (extend) して 共有クラス を定義することはできません。

コードエディターやインタープリターは、これらのルールが破られていても検知することはできません。コンパイラーおよび "シンタックスチェック" のみがエラーを生成します。

派生クラスは、Super コマンドを使って親クラスのコンストラクターを呼び出すことができます。

例題

Polygon クラスを継承した Square クラスを作成します。

// クラス: Square

// パス: Classes/Square.4dm

Class extends Polygon


Class constructor ($side : Integer)

// 親クラスのコンストラクターを呼び出します
// 長方形の高さ・幅パラメーターに正方形の一辺の長さを引数として渡します
Super($side;$side)
// 派生クラスにおいては、'This' を使用するより先に
// Super を呼び出しておく必要があります
This.name:="Square"



Function getArea() -> $area : Integer
$area:=This.height*This.width

Class function commands

The following commands have specific features when they are used within class functions:

Super

The Super command allows calls to the superclass, i.e. the parent class of the function. It can be called in the class constructor or in a class function code.

For more details, see the Super command description.

This

The This command returns a reference to the currently processed object. In most cases, the value of This is determined by how a class function is called. Usually, This refers to the object the function was called on, as if the function were on the object.

例:

//Class: ob

Function f() : Integer
return This.a+This.b

Then you can write in a method:

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

For more details, see the This command description.

クラスコマンド

4Dランゲージには、クラス機能を扱う複数のコマンドがあります。

OB Class

OB Class ( object ) -> Object | Null

OB Class は引数として渡したオブジェクトのクラスを返します。

OB Instance of

OB Instance of ( object ; class ) -> Boolean

objectclass、またはその子クラスに属していれば、OB Instance oftrue を返します。それ以外の場合は false を返します。

共有クラス

共有クラス を作成することができます。 共有クラスとは、クラスの new() 関数が呼び出されたときに、共有オブジェクト をインスタンス化するユーザークラスのことを指します。 共有クラスは共有オブジェクトしか作れません。

共有クラスは 共有関数 をサポートしています。共有関数は、Use...End use 構文なしで呼び出すことができます。

クラスが共有クラスかどうかは、Classオブジェクトの ..isSharedプロパティで確認できます。

info

共有クラスの作成

共有クラスを作成するには、Class Constructor の前に shared キーワードを追加します。 例:

// 共有クラス: Person
shared Class Constructor($firstname : Text; $lastname : Text)
This.firstName:=$firstname
This.lastName:=$lastname

// myMethod メソッド
var $person := cs.Person.new("John"; "Smith")
OB Is shared($person) // true
cs.Person.isShared // true

共有関数

共有クラス内で定義された関数が、そのクラスのオブジェクトを変更する場合には、共有オブジェクトへのアクセスを保護するために、Use...End use 構文を呼び出す必要があります。 しかし、shared として関数を定義することで、実行時には内部的な Use...End use を自動でトリガーするようにし、コードを簡略化することができます。

共有クラス内で共有関数を作成するには、Function キーワードの前に shared キーワードを追加します。 例:

// 共有クラス Foo
shared Class Constructor()
This.variable:=1

shared Function Bar($value : Integer)
This.variable:=$value // use/end use の呼び出しは不要です

共有クラスでないユーザークラス内で関数定義時に shared キーワードを使っても無視されます。

シングルトンクラス

シングルトンクラス とは、インスタンスを一つのみ作成するユーザークラスです。 シングルトンのコンセプトに関する詳細については、シングルトンに関する Wikipedia のページ を参照ください。

シングルトンの種類

4D は 3種類のシングルトンをサポートしています:

  • プロセスシングルトン は、自身がインスタンス化されたプロセス内において、インスタンスを一つのみ持つことができます。
  • 共有シングルトン は、マシン上のすべてのプロセスにおいて、共通のインスタンスを一つのみ持つことができます。
  • セッションシングルトン も共有シングルトンですが、特定の セッション 内のすべてのプロセスにおいて、共通のインスタンスを一つのみ持つことができます。 セッションシングルトンは、セッション内で全体的に共有されますが、セッションごとに異なります。 クライアントサーバーまたは Webアプリケーションのコンテキストで セッションシングルトンを使用すると、各セッションごと (つまり各ユーザーごと) に異なるインスタンスを作成して使用することができます。

アプリケーションやセッション、プロセス内のどこからでも利用可能な値を定義するのにシングルトンは便利です。

info

ORDAに基づいたデータモデルクラス では、シングルトンクラスはサポートされていません。

次の表は、作成された場所に応じたシングルトンインスタンスのスコープを示しています:

シングルトンが作成された場所プロセスシングルトンのスコープ共有シングルトンのスコープセッションシングルトンのスコープ
4Dシングルユーザープロセスアプリケーションアプリケーションまたは Web/RESTセッション
4D Serverプロセス4D Server のマシンクライアント/サーバーセッション、Web/RESTセッション、またはストアドプロシージャーセッション
4Dリモートモードプロセス (注意: シングルトンは "双子" プロセス間で同期されません)4Dリモートのマシン4Dリモートマシンまたは Web/RESTセッション

インスタンス化されると、シングルトンクラス (およびそのシングルトン) は、マシン上で実行中のアプリケーション内に参照が存在する限り存在し続けます。

シングルトンの作成と利用

シングルトンクラスを宣言するには、Class constructor の前に適切なキーワードを追加します:

  • (プロセス) シングルトンクラスを宣言するには、singleton Class constructor() と書きます。
  • 共有シングルトンクラスを宣言するには、shared singleton Class constructor() と書きます。
  • セッションシングルトンクラスを宣言するには、session singleton Class constructor() と書きます。
  • Session singletons are automatically shared singletons (there's no need to use the shared keyword in the class constructor).
  • Singleton shared functions support onHttpGet keyword.

クラスのシングルトンは、初回の cs.<class>.me プロパティの呼び出し時にインスタンス化されます。 インスタンス化されたクラスのシングルトンはその後、me プロパティの使用により常に返されます。

シングルトンを引数付きでインスタンス化する必要がある場合には、new() 関数を呼び出すこともできます。 この場合、アプリケーションの起動時に実行されるコードでシングルトンをインスタンス化することが推奨されます。

クラスがシングルトンクラスかどうかは、Classオブジェクトの ..isSingletonプロパティで確認できます。

クラスがセッションシングルトンかどうかは、Classオブジェクトの ..isSessionSingleton プロパティで確認できます。

例題

プロセスシングルトン

// クラス: ProcessTag
singleton Class Constructor()
This.tag:=Random

シングルトンを使うには:

// プロセス内で
var $mySingleton := cs.ProcessTag.me // 初回のインスタンス化
// 例: $mySingleton.tag = 5425
...
var $myOtherSingleton := cs.ProcessTag.me
// $myOtherSingleton.tag = 5425

// 別のプロセスで
var $mySingleton := cs.ProcessTag.me // 初回のインスタンス化
// 例: $mySingleton.tag = 14856
...
var $myOtherSingleton := cs.ProcessTag.me
// $myOtherSingleton.tag = 14856

共有シングルトン

// クラス: VehicleFactory

property vehicleBuilt : Integer

shared singleton Class constructor()
This.vehicleBuilt := 0 // 工場が完成させた車両の数

shared Function buildVehicle ($type : Text) -> $vehicle : cs.Vehicle

Case of
: $type="車"
$vehicle:=cs.Car.new()
: $type="トラック"
$vehicle:=cs.Truck.new()
: $type="スポーツカー"
$vehicle:=cs.SportCar.new()
: $type="オートバイ"
$vehicle:=cs.Motorbike.new()
Else
$vehicle:=cs.Car.new()
End case
This.vehicleBuilt+=1

すると、cs.VehicleFactory シングルトンを呼び出すことで、そのマシン上でアプリケーションのどこからでも 1行で新しい車両を取得することができます:

$vehicle:=cs.VehicleFactory.me.buildVehicle("トラック")

buildVehicle() 関数は (This.vehicleBuilt をインクリメントして) cs.VehicleFactory シングルトンを変更するので、shared キーワードを使う必要があります。

セッションシングルトン

在庫管理アプリケーションで、セッションシングルトンを使った在庫管理機能を実装します。

// クラス: ItemInventory

property itemList : Collection:=[]

session singleton Class constructor()

shared function addItem($item:object)
This.itemList.push($item)

ItemInventorクラスをセッションシングルトンとして定義することで、各セッションと各ユーザーが独自の在庫を持つことができます。 ユーザー在庫へのアクセスは以下のように簡単です:

// ユーザーセッションにおいて
$myList := cs.ItemInventory.me.itemList
// カレントユーザーの在庫リスト

参照

4D のシングルトン (ブログ記事)
セッションシングルトン (ブログ記事)