Menu
CoddyTech

クラスメソッドにおける非同期処理

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

ファクトリーメソッドを使った非同期初期化の処理方法がわかったところで、通常のインスタンスメソッドを非同期にする方法を見ていきましょう。これは簡単です。任意のメソッドにasyncを追加し、Futureを返すようにするだけです。

class WeatherService {
  String _location;
  
  WeatherService(this._location);
  
  Future<String> fetchTemperature() async {
    await Future.delayed(Duration(seconds: 1));
    return '22°C in $_location';
  }
  
  Future<void> updateLocation(String newLocation) async {
    await Future.delayed(Duration(milliseconds: 500));
    _location = newLocation;
    print('Location updated to $_location');
  }
}

Future<void> main() async {
  var service = WeatherService('London');
  var temp = await service.fetchTemperature();
  print(temp);
  
  await service.updateLocation('Paris');
}

非同期メソッドは、通常のメソッドと同じようにインスタンス変数にアクセスして変更できます。主な違いは、呼び出し元が結果をawaitする必要があることです。Future<void>を返すメソッドは値を返しませんが、処理が完了してから続行したい場合は、やはり待機する必要があります。

メソッド内で複数の非同期呼び出しを組み合わせたり、同じクラスのほかの非同期メソッドを呼び出したりすることもできます。

Future<String> getFullReport() async {
  var temp = await fetchTemperature();
  var humidity = await fetchHumidity();
  return '$temp, Humidity: $humidity';
}

このパターンは、APIやデータベースなどの外部リソースとやり取りするクラスや、時間のかかるあらゆる処理に不可欠です。

challenge icon

チャレンジ

簡単

非同期メソッドを使って株価を管理し、ポートフォリオの価値を計算する株式ポートフォリオトラッカーを作りましょう!リアルタイムの株価データの取得をシミュレートするクラスを作成し、複数の非同期処理を組み合わせてレポートを生成します。

コードを2つのファイルに分けます。

  • portfolio.dart: 株式とその数量を管理するStockPortfolioクラスを作成します。このクラスには、次のものが必要です。
    • 株式のシンボルと保有株数を保存する、_holdingsという名前のプライベートなMap<String, int>
    • _holdingsを空のマップとして初期化するコンストラクター
    • 株式の保有情報を追加または更新するメソッドaddStock(String symbol, int quantity)(非同期ではありません)
    • Future<double>を返す非同期メソッドfetchPrice(String symbol)。50ミリ秒の遅延をシミュレートしてから、シンボルの長さに25.5を掛けて計算した価格を返します。
    • Future<double>を返す非同期メソッドgetStockValue(String symbol)。シンボルに対応するfetchPriceを待機し、その価格に保有数量を掛けて合計額を返します。シンボルが保有株に含まれていない場合は、0.0を返します。
    • Future<double>を返す非同期メソッドgetTotalValue()。各株式についてgetStockValueを待機し、結果を合計して、すべての保有株の合計額を計算します。
    • Future<String>を返す非同期メソッドgenerateReport()。各株式の価値と合計額を示すレポートを作成します。各行は[symbol]: $[value]の形式(valueは小数点以下1桁)にし、最後の行はTotal: $[totalValue](こちらも小数点以下1桁)にします。
  • main.dart: ポートフォリオのファイルをインポートし、クラス内で非同期メソッドがどのように連携するかを示します。
    • StockPortfolioのインスタンスを作成します。
    • 次の保有株を追加します。AAPLを10株、GOOGLを5株、MSFTを8株
    • Fetching portfolio data...を出力します。
    • generateReport()の結果を待機して出力します。

generateReport()が同じクラス内のほかの非同期メソッドを呼び出していること、そして各メソッドがほかのメソッドの処理を積み重ねていることに注目してください。小数値の書式設定にはtoStringAsFixed(1)を使いましょう!

期待される出力:

Fetching portfolio data...
AAPL: $1020.0
GOOGL: $637.5
MSFT: $816.0
Total: $2473.5

自分で試してみよう

import 'portfolio.dart';

void main() async {
  // TODO: StockPortfolio のインスタンスを作成する

  // TODO: 保有銘柄を追加する:
  // - AAPL を 10 株
  // - GOOGL を 5 株
  // - MSFT を 8 株

  // TODO: "Fetching portfolio data..." を出力する

  // TODO: generateReport() の結果を待って出力する
}
quiz icon腕試し

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

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

自分で練習してみよう: Dartオンラインコンパイラ