Menu
Coddy logo textTech

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

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> を返すメソッドは値を返しませんが、処理を続行する前に完了を確実にしたい場合は、依然として await する必要があります。

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

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)。そのシンボルの fetchPriceawait し、保有数量を掛けて合計額を返します。シンボルが保有情報にない場合は 0.0 を返します
    • Future<double> を返す非同期メソッド getTotalValue()。各株式に対して getStockValueawait して結果を合計し、すべての保有資産の合計額を計算します
    • Future<String> を返す非同期メソッド generateReport()。各株式の価値と合計を表示するレポートを作成します。各行を [symbol]: $[value](値は小数点第1位まで)の形式にし、最後に Total: $[totalValue](これも小数点第1位まで)という行を続けます
  • main.dart: ポートフォリオファイルをインポートし、クラス内で非同期メソッドがどのように連携するかを示します:
    • StockPortfolio インスタンスを作成します
    • 次の保有情報を追加します:AAPL を10株、GOOGL を5株、MSFT を8株
    • Fetching portfolio data... と出力します
    • generateReport() の結果を await して出力します

generateReport() が同じクラス内の他の非同期メソッドをどのように呼び出し、各メソッドがどのように他のメソッドを基に構築されているかに注目してください。小数点以下の値をフォーマットするには toStringAsFixed(1) を使用してください!

期待される出力:

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

チートシート

インスタンスメソッドを非同期にするには、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');
  }
}

非同期メソッドは、インスタンス変数にアクセスしたり変更したりすることができます。呼び出し側は結果をawaitする必要があります。Future<void>を返すメソッドは値を返しませんが、完了を確実にするために依然としてawaitする必要があります。

非同期メソッドは、同じクラス内の他の非同期メソッドを呼び出すことができます。

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

このパターンは、APIやデータベースなどの外部リソースとやり取りするクラスにとって不可欠です。

自分で試してみよう

import 'portfolio.dart';

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

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

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

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

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

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