オブジェクト
オブジェクト型の変数・フィールド・式にはさまざまなデータを格納することができます。 4D のネイティブなオブジェクトの構造は、よくある "プロパティ/値" (または "属性/値") というペア (連想配列) に基づいています。 これらオブジェクトの記法は JSON をもとにしていますが、完全に同じというわけではありません。
プロパティ名は必ずテキストで表現されます。 プロパティ名には 命名規則 があります。
プロパティ値は以下のどれかの型で表現されます:
- 数値 (実数、整数、等)
- テキスト
- null
- ブール
- ポインター (
JSON Stringify
コマンドの使用、またはコピーの際に評価されます) - 日付 (日付型あるいは ISO日付フォーマット文字列)
- オブジェクト(1) (オブジェクトは入れ子にすることができます)
- ピクチャー(2)
- コレクション
(1) エンティティ や エンティティセレクション などの ORDAオブジェクトは オブジェクトフィールド には保存できませんが、メモリ内の オブジェクト変数 に保存することは可能です。
(2) デバッガー内でテキストとして表示したり、JSON へと書き出されたりした場合、ピクチャー型のオブジェクトプロパティは "[object Picture]" と表されます。
プロパティ名は大文字と小文字を区別するという点に注意してください。
オブジェクト型の変数・フィールド・式を操作するには オブジェクト記法 を用いるか、オブジェクト (ランゲージ) テーマが提供するコマンドを使用します。 オブジェクト型フィールドに対して処理をおこなうには QUERY BY ATTRIBUTE
、QUERY SELECTION BY ATTRIBUTE
や ORDER BY ATTRIBUTE
など、クエリ テーマの特定のコマンドも使用することができます。
オブジェクト記法を使ってアクセスされたそれぞれのプロパティ値は式とみなされます。 4D内で式が期待される場所であれば、どこでもこのような値を使用することができます:
- メソッド (コードエディター) に書いても、外部化(フォーミュラ、
PROCESS 4D TAGS
あるいは Web Server によって処理される 4D tags ファイル、4D Write Proドキュメントなど) しても使用可能です。 - デバッガー及びランタイムエクスプローラーの式エリア内。
- フォームエディターにおいて、フォームオブジェクトのプロパティリスト内。変数あるいは式フィールド内の他、様々なセレクションリストボックス及びカラムの式 (データソース、背景色、スタイル、フォントカラー等) において使用可能です。
インスタンス化
オブジェクトはあらかじめインスタンス化しておく必要があります。 初期化しない場合、プロパティ値の取得や変更はシンタックスエラーとなります。
オブジェクトのインスタンス化は、以下のいずれかの方法でおこなうことができます:
New object
コマンドを使用する。{}
演算子を使用する。
いくつかの 4Dコマンドや関数はオブジェクトを返します。たとえば、Get database measures
や File
などです。 この場合、オブジェクトを明示的にインスタンス化する必要はなく、4Dランゲージが代わりにおこなってくれます。
New object
コマンド
New object
コマンドは、新しい空の、またはプロパティが格納されたオブジェクトを作成し、その参照を返します。
例:
var $obVar : Object // オブジェクト型 4D変数の宣言
$obVar:=New object // オブジェクトのインスタンス化と 4D変数への代入
var $obFilled : Object
$obFilled:=New object("name"; "Smith"; "age";42) // プロパティが格納されたオブジェクトのインスタンス化と変数への代入
{}
演算子
{}
演算子を使って、オブジェクトリテラル を作成することができます。 オブジェクトリテラルとは、オブジェクトのプロパティ名とその値のペアが 0組以上含まれたセミコロン区切りのリストを中括弧 {}
で囲んだものです。 オブジェクトリテラルのシンタックスは、空の、またはプロパティが格納されたオブジェクトを作成します。
プロパティの値は式とみなされるため、プロパティ値に {}
を使ってサブオブジェクトを作成することができます。 また、コレクションリテラル を作成し、参照することもできます。
例:
var $o ; $o2 ; $o3 : Object // オブジェクト変数の宣言
$o := {} // 空のオブジェクトのインスタンス化
$o2 := {a: "foo"; b: 42; c: {}; d: ($toto) ? true : false } // プロパティを格納したオブジェクトのインスタンス化
// オブジェクト: {"a":"foo","b":42,"c":{},"d":false}
// 変数を使っても同様にオブジェクトをインスタンス化できます
var $a : Text
var $b : Integer
var $c : Object
$a:="foo"
$b:=42
$c:={}
$o3:={a: $a; b: $b; c: $c} // オブジェクト: {"a":"foo",b":42,"c":{}}
New object
とリテラルを使ったシンタックスは混在させることができます:
$o:={\
ob1: {age: 42}; \
ob2: New object("message"; "Hello"); \
form1: Formula(return This.ob1.age+10); \
form2 : Formula(ALERT($1)); \
col: [1; 2; 3; 4; 5; 6]\
}
$o.form1() // 52
$o.form2($o.ob2.message) // Hello と表示します
$col:=$o.col[5] // 6
通常オブジェクトと共有オブジェクト
二種類のオブジェクトを作成することができます:
New object
コマンド、またはオブジェクトリテラルのシンタックス{}
使用して作成する通常 (非共有) オブジェクト。 通常のオブジェクトは特別なアクセスコントロールをせずに編集可能ですが、プロセス間で共有することはできません。New shared object
コマンドを使用して作成する共有オブジェクト。 共有オブジェクトはプロセス間 (プリエンティブ・スレッド含む) で共有可能なオブジェクトです。 共有オブジェクトへのアクセスはUse...End use
構造によって管理されています。 詳細な情報については、共有オブジェクトと共有コレクション を参照ください。
オブジェクト記法の使用
オブジェクト記法を使うと、トークンのチェーンを通してオブジェクトのプロパティ値にアクセスすることができます。
オブジェクトプロパティ
オブジェクト記法では、オブジェクトプロパティは二通りの方法でアクセスすることができます:
- "ドット" 記号を使用する方法: > object.propertyName
例:
employee.name:="Smith"
- 大カッコと文字列を使用する方法: > object["propertyName"]
例:
$vName:=employee["name"]
// または:
$property:="name"
$vName:=employee[$property]
オブジェクトプロパティ値には、オブジェクトやコレクションも設定することが可能です。これらのサブプロパティにアクセスするため、オブジェクト記法では連続した字句を受け入れることができます:
$vAge:=employee.children[2].age
オブジェクトを格納、あるいは返すあらゆるランゲージ要素に対してオブジェクト記法を使用できます。たとえば:
- オブジェクト 自身 (変数、フィールド、オブジェクトプロパティ、オブジェクト配列、コレクション要素などに保存されているもの) 例:
$age:=$myObjVar.employee.age // 変数
$addr:=[Emp]data_obj.address // フィールド
$city:=$addr.city // オブジェクトプロパティ
$pop:=$aObjCountries{2}.population // オブジェクト配列
$val:=$myCollection[3].subvalue // コレクション要素
- オブジェクトを返す 4D コマンド 例:
$measures:=Get database measures.DB.tables
- オブジェクトを返す プロジェクトメソッド 例:
// MyMethod1
#DECLARE -> $o : Object
$o:=New object("a";10;"b";20)
// myMethod2
$result:=MyMethod1.a // 10
- コレクション 例:
myColl.length // コレクションの長さ
ポインター
注: オブジェクトは常に参照として渡されるため、通常はポインターを使用する必要はありません。 オブジェクトを引数として渡す際、4D 内部では自動的にポインターに類似したメカニズムを使うことでメモリの消費を最小限に抑え、引数を編集して返すことを可能にします。 つまり、ポインターは必要ないということです。 それでもポインターを使用したい場合には、プロパティ値はポインターを通してアクセスすることができます。
ポインターを使ってオブジェクトプロパティにアクセスするには、直接オブジェクトを使用する場合と方法が似ていますが、"ドット" 記号は省略する必要があります。
オブジェクト記法によるアクセス:
pointerOnObject->propertyName
大カッコを使用する方法:
pointerOnObject->["propertyName"]
例:
var vObj : Object
var vPtr : Pointer
vObj:=New object
vObj.a:=10
vPtr:=->vObj
x:=vPtr->a //x=10
Null 値
オブジェクト記法を使用する場合、null 値は Null コマンドを通してサポートされています。 このコマンドを使用すると、null 値をオブジェクトプロパティやコレクション要素に割り当てたり、それらと比較したりすることができます。例:
myObject.address.zip:=Null
If(myColl[2]=Null)
詳細については Null と 未定義 を参照ください。
未定義の値
オブジェクトプロパティを評価した結果、未定義の値が生成されることがあります。 未定義の式を読み込んだ、または割り当てようとしたときに 4D は通常、エラーを生成します。 ただし以下の場合には生成されません:
- 未定義のオブジェクトやプロパティ値を読み込むと未定義 (undefined) が返されます。未定義の値を (配列を除く) 変数に割り当てることは、
CLEAR VARIABLE
コマンドを使うのと同じ効果があります:
var $o : Object
var $val : Integer
$val:=10 // $val=10
$val:=$o.a // $o.a は未定義 (エラーなし) なため、この値を代入すると変数が初期化されます
// $val=0
- 未定義のコレクションの length プロパティは 0 を返します:
var $c : Collection // 変数は作成されたが、コレクションは未定義
$size:=$c.length // $size = 0
- 未定義の値を引数としてプロジェクトメソッドに渡した場合、宣言された引数の型に応じて、0 あるいは "" (空の文字列) へと自動変換されます。
var $o : Object
mymethod($o.a) // 未定義の引数を渡すと
// mymethod メソッド内では
#Declare ($myText : Text) // 引数の型はテキスト
// $myText の中身は ""
- 条件式で、If あるいは Case of キーワードで未定義と評価された場合には、自動的にfalse へと変換されます:
var $o : Object
If($o.a) // false
End if
Case of
:($o.a) // false
End case
- 未定義の値を既存のオブジェクトプロパティに代入した場合、その値は型に応じて初期化、あるいは消去されます:
- オブジェクト、コレクション、ポインター: Null
- ピクチャー: 空のピクチャー
- ブール: False
- 文字列: ""
- 数値: 0
- 日付: "オブジェクトではISO日付フォーマットの代わりに日付型を使用する" 設定が有効化されている場合は !00-00-00!、それ以外の場合には ""
- 時間: 0 (ミリ秒単位)
- 未定義、Null: 変化なし
var $o : Object
$o:=New object("a";2)
$o.a:=$o.b //$o.a=0
- 未定義の値を存在しないオブジェクトのプロパティへと代入した場合は、何も起こりません。
4Dコード内の式に対して特定の型であることが要求される場合、その式を適切な 4Dキャストコマンド (String
, Num
, Date
, Time
, Bool
) で囲うことで、たとえ未定義に評価されたとしても正しい型を確実に得ることができます。 これらのコマンドは式が未定義と評価された場合に、指定された型の空の値を返します。 例:
$myString:=Lowercase(String($o.a.b)) // 未定義の場合でもコード内でエラーが起きないように
// 文字列の値が得られるようにします
詳細については Null と 未定義 を参照ください。
例題
オブジェクト記法を使用すると、オブジェクトを扱う際の 4Dコードを単純化することができます。 同時に、コマンドベースの記法も引き続き完全にサポートされています。
- オブジェクトの読み書き (この例題ではオブジェクト記法とコマンド記法を比較します):
// オブジェクト記法を使用
var $myObj : Object // 4Dオブジェクト変数を宣言
$myObj:={} // オブジェクトリテラルを作成し、変数に代入
$myObj.age:=56
$age:=$myObj.age // 56
// コマンド記法を使用
var $myObj2 : Object // 4Dオブジェクト変数を宣言
OB SET($myObj2;"age";42) // オブジェクトを作成し、ageプロパティを追加
$age:=OB Get($myObj2;"age") // 42
// もちろん両方の記法を混用することもできます
var $myObj3 : Object
OB SET($myObj3;"age";10)
$age:=$myObj3.age // 10
- プロパティの作成と、オブジェクトを含む値の代入:
var $Emp : Object
$Emp:=New object
$Emp.city:="London" /// cityプロパティを作成し、その値を"London"に設定します
$Emp.city:="Paris" // cityプロパティを変更します
$Emp.phone:=New object("office";"123456789";"home";"0011223344")
// phoneプロパティを作成し、その値にオブジェクトを設定します
- オブジェクト記法を使用すると、サブオブジェクトの値を簡単に取得できます:
$vCity:=$Emp.city // "Paris"
$vPhone:=$Emp.phone.home // "0011223344"
- 大カッコ [ ] を使用すると文字列を使ってプロパティにアクセスできます:
$Emp["city"]:="Berlin" // city プロパティを変更
// これは変数を通してプロパティを作成する場合に便利です
var $addr : Text
$addr:="address"
For($i;1;4)
$Emp[$addr+String($i)]:=""
End for
/// $Emp object には 4つの空のプロパティ "address1...address4" が作成されました