Menu
Coddy logo textTech

call() メソッド

CoddyのDartジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 73/110。

Dartには、オブジェクトを関数のように使用できるようにするcall()という名前の特別なメソッドがあります。クラスがcall()メソッドを定義している場合、関数呼び出しの構文を使用して、そのクラスのインスタンスを呼び出すことができます。

class Multiplier {
  int factor;
  
  Multiplier(this.factor);
  
  int call(int value) {
    return value * factor;
  }
}

void main() {
  var double = Multiplier(2);
  var triple = Multiplier(3);
  
  print(double(5));  // 10 - オブジェクトを関数のように呼び出す
  print(triple(5));  // 15
}

double.call(5) と書く代わりに、単に double(5) と書くことができます。オブジェクトに対して括弧を使用すると、Dart は自動的に call() メソッドを呼び出します。

call() メソッドは、通常のメソッドと同じように、任意のパラメータを受け取り、任意の型を返すことができます。

class Greeter {
  String prefix;
  
  Greeter(this.prefix);
  
  String call(String name, {String punctuation = '!'}) {
    return '$prefix, $name$punctuation';
  }
}

void main() {
  var hello = Greeter('Hello');
  print(hello('Alice'));  // Hello, Alice!
  print(hello('Bob', punctuation: '?'));  // Hello, Bob?
}

このパターンは、関数のようにはたらきながら、状態や設定も保持する必要があるオブジェクトが必要な場合に便利です。これは、呼び出しの間に設定を記憶しておく必要がある、再利用可能な操作、バリデータ、またはフォーマッタを作成するためによく使用されます。

challenge icon

チャレンジ

簡単

フォーマッタオブジェクトを関数のように直接呼び出すことができるテキストフォーマットシステムを構築しましょう!設定を保持しながら、さまざまな方法でテキストを変換するコーラブル(呼び出し可能)クラスを作成します。

コードを2つのファイルに整理します:

  • formatters.dart: 文字列を変換する2つのコーラブルクラスを作成します:
    • 設定可能な接頭辞(prefix)と接尾辞(suffix)でテキストを囲む Wrapper クラス。prefixsuffix 文字列を保持し、その call() メソッドは String text を受け取り、接頭辞と接尾辞で囲まれたテキストを返す必要があります。
    • テキストを設定された回数だけ繰り返す Repeater クラス。整数の times を保持し、その call() メソッドは String text を受け取り、その回数分繰り返されたテキストをスペース区切りで返す必要があります。
  • main.dart: フォーマッタをインポートし、これらのオブジェクトが関数のようにどのように使用できるかを実演します:
    • 接頭辞 '[' と接尾辞 ']' を持つ Wrapper を作成します。
    • 接頭辞 '***' と接尾辞 '***' を持つ別の Wrapper を作成します。
    • times3 に設定した Repeater を作成します。
    • 最初のラッパーを 'Hello' で呼び出し、結果を表示します。
    • 2番目のラッパーを 'Important' で呼び出し、結果を表示します。
    • リピーターを 'Go' で呼び出し、結果を表示します。
    • 最初のラッパー(引数は 'Nested')の結果を2番目のラッパーに渡すことでチェイニングを実演し、結果を表示します。

通常の関数と同じように、括弧を使用してフォーマッタオブジェクトを直接呼び出すことができることに注目してください。call() メソッドがこれを可能にし、各オブジェクトは使用の合間もその設定を保持します!

期待される出力:

[Hello]
***Important***
Go Go Go
***[Nested]***

チートシート

call() メソッドを使用すると、オブジェクトをあたかも関数であるかのように扱うことができます。クラスが call() メソッドを定義している場合、そのクラスのインスタンスを関数呼び出し構文を使用して呼び出すことができます。

class Multiplier {
  int factor;
  
  Multiplier(this.factor);
  
  int call(int value) {
    return value * factor;
  }
}

void main() {
  var double = Multiplier(2);
  print(double(5));  // 10 - オブジェクトを関数のように呼び出している
}

double.call(5) と書く代わりに、単に double(5) と書くことができます。Dart は、オブジェクトに対して括弧を使用すると、自動的に call() メソッドを呼び出します。

call() メソッドは、任意のパラメータを受け取り、任意の型を返すことができます:

class Greeter {
  String prefix;
  
  Greeter(this.prefix);
  
  String call(String name, {String punctuation = '!'}) {
    return '$prefix, $name$punctuation';
  }
}

void main() {
  var hello = Greeter('Hello');
  print(hello('Alice'));  // Hello, Alice!
  print(hello('Bob', punctuation: '?'));  // Hello, Bob?
}

このパターンは、関数のよう振る舞いながらも、呼び出し間で状態や設定を保持するオブジェクトを作成するのに便利です。

自分で試してみよう

import 'formatters.dart';

void main() {
  // TODO: 接頭辞 '[' と接尾辞 ']' を持つ Wrapper を作成してください
  
  // TODO: 接頭辞 '***' と接尾辞 '***' を持つ別の Wrapper を作成してください
  
  // TODO: times を 3 に設定した Repeater を作成してください
  
  // TODO: 最初の wrapper を 'Hello' で呼び出し、結果をプリントしてください
  
  // TODO: 2番目の wrapper を 'Important' で呼び出し、結果をプリントしてください
  
  // TODO: repeater を 'Go' で呼び出し、結果をプリントしてください
  
  // TODO: 最初の wrapper の結果('Nested' を使用)を 2番目の wrapper に渡すことで
  // チェイニングを実演し、その結果をプリントしてください
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン