クラスに計算プロパティが登場!

4D の開発環境にクラスが登場したことで、プログラミングがよりモダンに、より簡単にスケールできるようになりました。クラスにおいては、プロパティや関数の定義を可能なほか、継承をサポートします。
アプリケーションで、科学データあるいは会計データを管理するクラスを使うことがあるかもしれません。会計データを例に考えてみます。たとえば、税金を計算する関数を作成したとします。また、複数の国を管理している場合、異なるルールを管理するために継承を使用するかもしれません。そして、これらの結果をリストボックスに表示します。しかし、フォーミュラ内で使用されている属性のひとつをユーザーが変更した場合、結果を更新するにはイベントを管理する必要があります。
4D v19 R3 では、計算プロパティのおかげで、このプロセスを簡素化することができます。計算プロパティのゲッターとセッター関数を定義し、このプロパティをリストボックスに追加すると、すべてが 4D によって自動的に処理されます。UI にビジネスロジックを入れる必要はありません。

HDI: クラス: 計算プロパティ

定義と計算

 
このコンセプトの威力を説明するために、できるだけシンプルに、具体例を使って説明しましょう:
“Rectangle” (長方形) クラスは、 width height という 2つのプロパティを持ちます。このクラスには、getSurface() getPerimeter() のような関数が定義されるかもしれません。
 
しかし、surface (面積) と perimeter (周長) が普通のプロパティのように使えたら便利と思いませんか? 読み取ることができ、場合によっては変更も可能なプロパティです。そして、それらに依存する他のプロパティも自動で変更できたら…? 計算プロパティのおかげで、これらのことが可能になりました。
 

手品のよう!

ここに 2つの簡単な例があります。どちらの場合も、すべてのプロパティを入力することができます。

widthheight を変更すると、perimetersurface が再計算されます。逆に、surfaceperimeter を変更すると、widthheight がそれに応じて変化します:

blank

 
 
 
 
 
 
 
 
 
これは、リストボックス内でも有効です。リストボックスは、任意の列でソートすることもできます!
 
blank

 

タネと仕掛けはどこに…?

どちらの場合も、舞台裏にスクリプトはありません! 計算は、Rectangle クラス内で一回きり定義されているだけです。もし、これらのプロパティを使ったフォームが複数必要になっても、追加のコードを書く必要はありません。

では、どのような仕組みになっているのか、見てみましょう。

 

計算プロパティへのアクセス

GET

最初の関数 get” は、プロパティがどのように計算されるかを定義します。つまり、計算結果を返さなくてはなりません。
計算プロパティの定義に必須なのはこの関数だけです。この関数が定義されているだけで、計算プロパティは存在し、使用することができます。

get surface 関数は Rectangleクラス内で定義します:

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

上の関数が書けたら、surface プロパティを普通のプロパティと同様に扱うことができるようになります。

$rect:=cs.Rectangle.new(60; 20)
$surface:=$rect.surface  // surface プロパティを取得します
ALERT("この長方形の面積: "+String($surface))

SET

2つ目の関数  “set” が存在する場合、これは計算プロパティの変更を管理します。面積の変更により、長方形の幅と高さの値を再計算することができます。
 

// この関数は、surfaceプロパティが変更されたときに呼び出されます
Function set surface
($surface)

// 縦横比を維持します
$ratio:=This.width/This.height

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

上記の関数を書くと、surface プロパティは普通のプロパティと同様に変更することができます。widthheight の属性は、それに応じて調整されます。

// 幅60 x 高さ20 の長方形を作成します
$rect:=cs.Rectangle.new(60; 20)
$surface:=$rect.surface  // surface プロパティを取得します

ALERT("この長方形の面積: "+String($surface))  // 120 を返します
// 面積を変更してみましょう

$rect.surface:=1000
// 更新された幅と高さを表示します
$width:=$rect.width
$height:=$rect.height
ALERT("この長方形の寸法: "+String($width)+" x "+String($height))  // 54.77 x 18.25 を返します

 

クエリとソート

Rectangleクラスのオブジェクトを複数格納するコレクションは、計算プロパティを使った クエリソート もおこなうことができます!

クエリの例です:

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

ソートの例です:

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

 

…そしてJSON

オブジェクトが計算プロパティを持つ場合、これらのプロパティは “stringify” (文字列化) の際に考慮されます。

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

blank

まとめ

この簡単な例題は、複雑な処理が可能でありながら、その複雑さは隠されたまま表には出てこないことを示しています。
また、クラス内でルールを定義できるため、コンテキストやユーザー権限などに応じたデータ公開をより管理することができます。
現代的なプログラミング手法へようこそ!
 
詳しくは、このドキュメントを参照ください。
 
 
Roland Lannuzel
- プロダクトオーナー&4Dエキスパート -電子工学を学んだ後、産業用ITの分野で開発者兼コンサルタントとして、さまざまなデータベースやテクノロジーを使って顧客のためのソリューションを構築。80年代後半に4Dに惚れ込み、会計、請求書作成、メールシステムなどのビジネスアプリケーションの作成に4Dを使用してきました。現在も、新機能やデータベース開発ツールの定義など、4Dの未来を積極的に切り開いています。