メソッド

メソッドを使用すると、関連付けられたクラスのインスタンスであるオブジェクトに関数を実行することができます。メソッドには、Curl® 言語の他の関数と同様の構文および意味があります。
サブクラスを作成すると、そのサブクラスはスーパークラスのメソッドを継承します。ただし、そのサブクラス側でメソッドの定義をオーバーライドすることができます。メソッドがリストされた引数を取る場合は、オーバーライドするメソッドはキーワード引数を含む同一のリストされた引数を取る必要があります。メソッドが残余引数を取る場合は、オーバーライドするメソッドも残余引数を取る必要があります。
構文:{method [access] [modifier-list] {method-name [arg-list]}:[return-types]
    code-body
},
パラメータ:
accessはアクセス属性です。有効な属性は publiclibrarypackageprotected および private です。access を指定しない場合は、アクセス属性は既定で package に設定されます。詳細については、「メソッドのアクセス属性」を参照してください。
modifier-listは修飾子のオプションのリストです。メソッドの有効な修飾子は abstractinlinefinalsealedopen および deprecated です。詳細については、「メソッドの修飾子」を参照してください。
method-nameはメソッド名です。Curl 言語のメソッドの命名規則では、小文字のみ使用されます。メソッド名に複数の単語がある場合は、ハイフンを使用して単語を区切ります。
arg-listはメソッドの引数のリストです。リストされた引数または残余引数を指定することができます。引数は位置フォーマットまたはキーワード フォーマットを持つことができます。コンマを使用して指定する引数を区切ります。詳細については、「メソッドの引数の指定」を参照してください。
return-typesはメソッドの戻り値のデータ型です。メソッドは 1 つ以上の値を返すことができます。return-type を指定しない場合は、any のデータ型による戻り値が想定されます。詳細については、「メソッドの戻り値のデータ型を指定」を参照してください。
code-bodyはメソッドの本体です。code-body はコードブロックです。コードブロックは、オプションの return 式を含む 1 つ以上の Curl 言語の式で構成されています。 メソッドが 1 つ以上の値を返すように定義する場合は、return 式を記述する必要があります。return 式を記述すると、 Curl® 実行環境 (RTE) では、そのメソッドを呼び出す式に return 式の値を返します。
注意: access および modifier-list を任意の順序で指定することができます。たとえば、
{method public abstract ...}

{method abstract public...}
は両方とも有効です。
たとえば、次のコードでは値 (void) を返さない my-method と呼ばれるメソッドが作成されています。このメソッドはデータ型 anyarg という名前の 1 つの引数を取ります。このメソッドはパブリック メソッドで、修飾子は付いていません。
{method public {my-method arg:any}:void
    || body of method
}
次のコードでは、2 つの整数値を返す my-method と呼ばれるメソッドが作成されています。このメソッドはデータ型 anyarg という名前の 1 つの引数を取ります。このメソッドはパブリック メソッドで、修飾子は付いていません。
{method public {my-method arg:any}:(int, int)
    || body of method
    {return my-int-1, my-int-2}
}

メソッドの修飾子を指定

要約:
  • abstract は抽象メソッドを示します。
  • inline により、コンパイラはメソッドの呼び出しを実際のメソッドのコードに置換します。
  • final は、サブクラスがこのメソッドをオーバーライドすることができないことを示します。
  • sealed は、他のパッケージ内のサブクラスがこのメソッドをオーバーライドすることができないことを示します。
  • open は、任意のサブクラスがこのメソッドをオーバーライドすることができることを示します。
  • deprecated は、このメソッドの新規コードでの使用は適さず、後に削除される場合があることを示します。
修飾子を使用してメソッドのコンパイルの仕方を変更することができます。修飾子の指定はオプションです。複数の修飾子を指定する場合は、スペースを使用して修飾子を区切ります。メソッドには次の修飾子があります。
abstract を使用して抽象メソッドを示します。抽象メソッドは定義されるクラス内に実装されていないメソッドです。サブクラスのメソッドにはメソッドが実装される必要があります。抽象メソッドはさまざまな実装に対応する共通のインターフェースになります。抽象メソッドにはコード本体は一切ありません。次に、抽象メソッドの例を示します。
{method public abstract
    {request-draw
    layout-context:LayoutContext={self.get-layout-context}}:void
}
注意: 抽象クラスのみに抽象メソッドを定義することができます。
inline を使用して、コンパイラにメソッドの呼び出しを実際のメソッドのコードに置換することを示します。一定の条件下で、インライン メソッドを使用するとコードの実行時間が早くなります。通常、こうした条件にはさまざまな場所からは呼び出されない小さなメソッドが含まれます。inline が記述されていると、コンパイラがメソッドのインライン置換を実行します。ただし、インライン置換を実行する前にコンパイラがインライン置換でパフォーマンスが向上するかどうかを判別します。コンパイラがそのインライン置換でパフォーマンスが向上しないと判別する場合は、置換は実行されません。
final を使用して最後のメソッドを示します。サブクラスは最後のメソッドをオーバーライドすることができません。サブクラスがメソッドをオーバーライドする必要があるかどうかを判別するのはむずかしい場合もあります。ただし、メソッドがオーバーライドされないことがわかっていれば、final の修飾子を使用する必要があります。final の修飾子を使用すると、コンパイラはより小さくて、高速なコードを生成します。private アクセスを指定したメソッドは、そのクラスの外からは不可視なので暗黙に final になることに注意してください。
sealed を使用してシールド メソッドを示します。他のパッケージ内のサブクラスは、シールド メソッドをオーバーライドすることができません。メソッドが他のパッケージのクラスでオーバーライドされない場合やできない場合は、 sealed の修飾子を使用する必要があります。sealed の修飾子を使用すると、コンパイラはより小さくて、高速なコードを生成します。package アクセスを指定したメソッドは、それ自体のパッケージの外からは不可視なので、宣言することができず暗黙にシールドされます。
メソッドが任意のサブクラスでオーバーライド出来ることを示すのに open を使用することができます。これは任意の publiclibraryまたは protected メソッドの既定のオーバーライド属性です。
注意: コンパイラのディレクティブ allow-implicit-open? = false の実行時 (この設定はコンパイラのディレクティブ stringent? = true により暗黙に定義されます) は、明示的なオーバーライド属性を指定する必要があります。open, つまり、定義するメソッド(またはクラス) ごとに sealed または final を指定します。詳細については、「コンパイラのディレクティブ」のセクションを参照してください。
deprecated を使用すると、このメソッドが新規コードでの使用に適さず後に削除される場合があることを示します。

メソッドのアクセス属性を指定

要約:
  • public は全コードがメソッドを呼び出すことができることを示します。
  • library は同じライブラリのコードだけが、フィールドにアクセスできることを示します。
  • package は同じパッケージ内のコードのみがメソッドを呼び出すことができることを示します。
  • protected は同じパッケージ内のコードまたはサブクラス内のコードのみがメソッドを呼び出すことができることを示します。
  • private は同じクラス内のコードのみがメソッドを呼び出すことができることを示します。
  • 既定値は package です。
アクセス属性はメソッドにアクセスできるコードを示します。アクセス属性は保護属性としても知られています。コードがメソッドにアクセスするには、コードが最初にメソッドを含むクラスにアクセスする必要があります。アクセス属性の指定はオプションです。メソッドに対して有効なアクセス属性は次の 4 つです。
package は既定のアクセス属性です。つまり、アクセス属性を指定しない場合、メソッドは アクセス属性 package を想定します。
全コードにメソッドへアクセスさせるには、public を使用します。メソッドと同じパッケージ内のコードにアクセスを制限するには package を使用します。メソッドと同じパッケージ内のコードまたはサブクラス内のコードにアクセスを制限するには protected を使用します。アクセス属性に関する詳細情報は、libraryを参照してください。
メソッドと同じクラス内のコードにアクセスを制限するには private を使用します。プライベート メソッドは、それらが定義されるクラス内からのみアクセスすることができます。サブクラスはプライベート メソッドを継承しません。つまり、スーパークラス内で private メソッドと同じ名前が付いたメソッドを持つことができるということです。

メソッドの引数を指定

要約:
  • プロシージャの引数の指定と同様
  • 位置フォーマットまたはキーワードのフォーマットにリストされた引数を指定できます。
  • リストされた引数を指定する場合は、オーバーライドするメソッドに、同じ引数のリストを指定する必要があります。
  • 位置引数のフォーマット:arg-name[:arg-type]
  • キーワード引数のフォーマット:arg-name[:arg-type]=arg-value
  • 残余引数 (...) を指定できます。
  • 残余引数を指定する場合は、オーバーライドするメソッドに、残余引数も指定する必要があります。
  • 残余引数の記述がある場合は、その引数は最後に指定した引数でなければなりません。
  • オーバーライドするメソッドには同じ戻り値のデータ型を指定する必要があります。
引数には次の 2 つのカテゴリがあります。

リストされた引数の指定

リストされた引数を次に示します。
位置引数のフォーマットに引数を指定するには、次の構文を使用します。
arg-name[:arg-type]
arg-name は一意で有効な Curl 言語の修飾子で、arg-type は有効な Curl 言語のデータ型です。 arg-type はオプションです。arg-type の既定の値は any のデータ型です。つまり、データ型をしない場合、引数は any のデータ型を想定します。位置引数の定義の例は次のとおりです。
|| A method that takes one integer positional
|| argument (i)
{method public {my-method1 i:int}:void
    || Body of method
}

|| A method that takes one "any" positional
|| argument (a)
{method public {my-method2 a}:void
    || Body of method
}

|| A method that takes two positional arguments:
|| a bool (b) and a char (c)
{method public {my-method3 b:bool, c:char}:void
    || Body of method
}
キーワード引数を指定するには、次の構文を使用します。
arg-name[:arg-type]=arg-value
arg-name は一意で有効な Curl 言語の修飾子で、arg-type は有効な Curl 言語のデータ型です。 arg-value は引数の既定の値です。arg-type の既定の値は any のデータ型です。つまり、データ型を指定しない場合、引数は any のデータ型を想定します。キーワード引数の定義の例は次のとおりです。
|| A method that takes one integer keyword
|| argument (i)
{method public {my-method4 i:int=0}:void
    || Body of method
}

|| A method that takes two keyword arguments:
|| a bool (b) and a char (c)
{method public {my-method5 b:bool=true, c:char='a'}:void
    || Body of method
}
メソッドがリストされた引数を取り、そのメソッドをサブクラスでオーバーライドする場合は、オーバーライドするメソッドは同一のリストされた引数を取る必要があります。つまり、そのメソッドは同じ数字と型の位置引数および同じ名前と型のキーワード引数を取る必要があります。キーワード引数の既定値は該当する位置引数の変数名と同様、変更することができます。

残余引数の指定

残余引数を指定する場合は、3 つのピリオド (...) を引数リストの最後に含めます。例:
|| A method that takes rest arguments.
{method public {my-method6 ...}:void
    || Body of method
}

|| A method that takes two keyword arguments:
|| a bool (b) and a char (c) and rest arguments.
{method public {my-method7 b:bool=true, c:char='a', ...}:void
    || Body of method
}
メソッドが残余引数を取り、そのメソッドをサブクラスでオーバーライドする場合は、オーバーライドするメソッドも残余引数を取る必要があります。たとえば、次のクラス階層を見てみます。
Grid
Table
Visual.add メソッドは両方のクラスで継承されています。そのシグネチャは次のとおりです。
{Visual.add g:any, ...}:Visual
Visual.add は 1 つのリストされた引数 (g) および残余引数を取ります。ただし、add の実装については Grid の残余引数と Table の残余引数は異なります。たとえば、Gridhorigin および vorigin に対してキーワード引数を取ります。一方、Tablecolspan および rowspan に対してキーワード引数を取ります。

メソッドの戻り値のデータ型を指定

要約:
  • プロシージャの戻り値のデータ型の指定と同様
  • 戻り値を一切指定しない場合:voidまたは()
  • 1 つの戻り値を指定する場合:return-typeまたは(return-type)
  • 複数の戻り値を指定する場合:(return-type-list)
  • 既定では、メソッドは any データ型で 1 つの値を返します。
メソッドが返す値のデータ型を指定できます。メソッドが値を返さない場合は、必ず戻り値に対して void を指定します。 (注:戻り値を指定しないことと、戻り値がないこととは同じではありません。この詳細については後で説明します。) 値を返さないメソッドの例を次に示します。
|| A method that does not return a value.
{method public {my-method8 i:int}:void
    || Body of method
}
メソッドが 1 つの値を返す場合は、その値のデータ型を指定します。例:
|| A method that returns one value: an int.
{method public {my-method9 i:int}:int
    || Body of method
}
メソッドが複数の値を返す場合は、次の構文を使用します。
(return-type-list)
return-type-list は戻り値のデータ型のリストです。コンマを使用してデータ型を区切ります。例:
|| A method that returns three values: an int, a String,
|| and a bool.
{method public {my-method i:int}:(int, String, bool)
    || Body of method
}
メソッドが複数の値を返す場合、Curl 言語では戻り値のデータ型の仕様で修飾子がインクルードされます。この修飾子は、コードを読む際に各戻り値の内容を示す以外は何の役にも立ちません。つまり、ドキュメントのフォームまたはコードを読む際のコメントの働きをします。実行環境でコードがコンパイルされると、修飾子は廃棄されます。戻り値の修飾子の使用状況を理解するために、次のメソッドを見てみます。
|| A method that returns three String values.
{method public {customer i:int}:(String, String, String)
    || Body of method
}
各戻り値の内容を説明する修飾子をインクルードすると、このメソッドの目的がさらに明らかになります。例:
|| A method that returns three String values.
{method public {customer}:(first:String, last:String, addr:String)
    || Body of method
}
戻り値のデータ型はオプションであることに留意してください。戻り値のデータ型を指定しない場合は、any のデータ型による1 つの戻り値が想定されます。例:
|| A method that returns one value: an any.
{method public {my-method i:int}
    || Body of method
}
オーバーライドするメソッドには、対象のメソッドと同じ数字および戻り値のデータ型を指定する必要があります。

メソッドから値を返す

要約:
  • プロシージャから値を返すのと同様
  • 1 つの戻り値:{return return-value}
  • 複数の戻り値: {return return-value-list}
メソッドが値を返すように定義する場合は、メソッドの本体に return 式をインクルードする必要があります。return 式は、メソッドが返す変数ごとに 1 つの引数を取ります。戻り値のデータ型は、メソッドのシグネチャに指定した戻り値のデータ型のサブタイプでなければなりません。たとえば、次のメソッドは 1 つの整数値を返します。
|| A method that returns one value: an int.
{method public {my-method i:int}:int
    {return i * 2}
}
次の例で 3 つの値を返すメソッドを示します。コンマを使用して戻り値を区切ることに注意してください。
|| A method that returns three String values.
{method public {my-method}:(first:String, last:String, addr:String)
    || Define three variables to hold the information that
    || this method returns.
    let first:String
    let last:String
    let addr:String
    || Code that places information in the variables.
    ...
    || Return the information
    {return first, last, addr}
}
return 式の引数としてプロシージャまたはメソッドの呼び出しを指定することもできます。プロシージャまたはメソッドの呼び出しを指定すると、少なくとも所定の数の戻り値を返します。所定の戻り値数以上を返しても、その余分の値は無視されます。プロシージャまたはメソッドの呼び出しからの戻り値のデータ型は、このメソッドからの戻り値のデータ型のサブタイプでなければなりません。

メソッドの継承

要約:
  • サブクラスはそのスーパークラスから全メソッドを継承します。
  • 継承されたメソッドをオーバーライドできます。
スーパークラスから継承するクラスを作成すると、そのクラスはそのスーパークラスのメソッドを継承します。複数のスーパークラスから継承するクラスを作成すると、そのクラスはその全スーパークラスのメソッドを継承します。
クラスが継承するメソッドをオーバーライドすることができる場合がほとんどです。メソッドがリストされた引数を取る場合は、オーバーライドするメソッドは同じリストされた引数を取ります。メソッドが残余引数を取る場合は、オーバーライドするメソッドも残余引数を取ります。元のメソッドおよびオーバーライドするメソッドは同じ戻り値のデータ型を持つ必要があります。
Curl 言語では、クラスは複数のスーパークラスから継承できます。.複数の継承をサポートする言語では、名前衝突を避けるメソッドを持つことができます。クラスが 2 つ以上のメソッドを同じ名前で継承したり、複数のメソッドのいずれかが他の全メソッドのサブクラスにある場合、コンパイラは名前衝突を避けるメソッドを使用します。そのようなメソッドが存在しない場合は、コンパイラはエラーを返します。次にいくつかの例を示します。
次の図に一致するコードの場合、 D クラスは C クラスで a メソッドを使用します。
A クラス
(a メソッドを定義します)。
B クラス
C クラス
(a メソッドをオーバーライドします)。
D クラス
C クラスと同様メソッド a
を使用します。
{define-class shared A
  ...
  {method {a}:void ...}
}
{define-class B {inherits A}
  ...
}
{define-class C {inherits A}
  ...
  {method {a}:void ...}
}
{define-class D {inherits B, C}
  ...
}
Figure: オーバーライドされるメソッドの継承
次の図に一致するコードは、エラーを返します。
A クラス
(a メソッドを定義します)。
B クラス
C クラス
(a メソッドを定義します)。
D クラス
エラー !
{define-class A
  ...
  {method {a}:void ...}
}
{define-class B {inherits A}
  ...
}
{define-class C
  ...
  {method {a}:void ...}
}
{define-class D {inherits B, C}
  ...
}
Error!
Figure: オーバーライドされない複数のメソッドの継承:ケース 1
次の図に一致するコードも、エラーを返します。
B クラス
(a メソッドを定義します)。
C クラス
(a メソッドを定義します)。
クラス D
エラー !
{define-class B
  ...
  {method {a}:void
    ...}
}
{define-class C
  ...
  {method {a}:void
    ...}
}
{define-class D {inherits B, C}
  ...
}
Error!
Figure: オーバーライドされない複数のメソッドの継承:ケース 2

メソッドの呼び出し

要約:
  • プロシージャの呼び出しに似ています。
  • メソッドの呼び出し:{object.method-name [arguments-list]}
  • 複数の戻り値 (通常): set (variable-list) = {object.method-name [arguments-list]}
メソッドにアクセスするコードであれば、そのメソッドを呼び出すことができます。全コードが public アクセス属性を使用してメソッドにアクセスします。ただし、同じパッケージ内のコードのみが package アクセス属性を使用してメソッドにアクセスします。パッケージの詳細については、「パッケージ」を参照してください。
メソッドを呼び出すには、次の構文を使用します。
{object.method-name [arguments-list]}
object は値が該当するデータ型のオブジェクトになる式です。method-name はメソッド名で、arguments-list はメソッドを呼び出す引数のリストになります。(object のデータ型は any またはメソッドを定義するクラスのサブタイプのいずれかになります)。複数の引数を指定する場合は、コンマを使用して引数を区切ります。メソッドを呼び出す際には、キーワード引数を任意の場所および順序で指定することができます。ただし、メソッド定義と同じ順序で位置引数を指定する必要があります。位置引数間にキーワード引数をインクルードできます。ただし、位置引数の相対順序を相互に保持する必要があります。
メソッドが複数の値を返す場合は、let または set ステートメントを使用して戻り値を変数に代入することができます。let ステートメントを使用するには、次の構文を使用します。
let (variable-definition-list) = {object.method-name [arguments-list]}
variable-definition-list は変数定義のリストです。variable-definition-list 内で、コンマを使用して変数定義を区切ります。各変数定義の構文は次のとおりです。
variable-name[:data-type]
例:
let (x:char, y:int) = {my-object.my-method}
set ステートメントを使用するには、次の構文を使用します。
set (variable-list) = {object.method-name [arguments-list]}
例:
let x:char
let y:int
set (x, y) = {my-object.my-method}
複数の値を返すメソッドを呼び出す際に、全戻り値を変数に代入する必要はありません。実際にそのようなメソッドを呼び出す際には、戻り値の任意数を変数に代入することができます。戻り値は左から右の順に変数に代入され、代入されない戻り値は破棄されます。この機能を使用して、複数の戻り値 (常時使用しない戻り値を含む) を返すメソッドを作成できます。