基礎
Hello World
main()はDartプログラムのエントリポイントです
// Hello World in Dart
void main() {
print('Hello, World!');
}
/* Multi-line
block comment */
/// Documentation comment
/// Supports Markdown
void greet(String name) {
print('Hi, $name');
}コメント
ドキュメントコメントはMarkdownをサポートしています
var name = 'Alice'; // type inferred
String city = 'NYC'; // explicit type
final age = 30; // runtime constant
const PI = 3.14; // compile-time constant
final now = DateTime.now(); // OK: runtime value
// const time = DateTime.now(); // ERROR: not compile-time
const list = [1, 2, 3]; // const list (immutable)
final list2 = [4, 5, 6]; // final ref, mutable contentセミコロン
すべての文はセミコロンで終わる必要があります
int value = 42; // non-nullable
int? nullableValue; // nullable (default null)
print(nullableValue); // null
print(nullableValue ?? 0); // 0 (null coalescing)
nullableValue ??= 10; // assign if null
print(nullableValue); // 10
// int x = null; // ERROR: non-nullable
String name = 'Alice';
print(name.length); // safe, no null check出力
printは自動的に改行を追加します
import 'dart:io';
void main() {
print('Hello'); // stdout with newline
stdout.write('no newline'); // no trailing newline
stderr.writeln('an error'); // stderr with newline
String? input = stdin.readLineSync(); // read a line
int? n = int.tryParse(input ?? ''); // safe parse
print('You entered: $n');
}変数宣言キーワード
var/finalを優先
var x = 10; // inferred as int
var y = 3.14; // inferred as double
var s = 'hi'; // inferred as String
dynamic d = 10; // type can change
d = 'now string'; // OK
// d.foo(); // compiles, may fail at runtime
Object o = 'hello'; // supertype of all non-null types
// o.length; // ERROR: Object has no length
print((o as String).length); // 5 (cast)変数
var型推論
コンパイラが自動的に型を推論します
int a = 42;
double b = 3.14;
num c = 10; // num is supertype of int & double
num d = 2.71;
print(a.bitLength); // 6
print(b.toStringAsFixed(2)); // '3.14'
print(10 ~/ 3); // 3 (integer division)
print(10.remainder(3)); // 1
print(0xFF); // 255 (hex)
print(1.5e3); // 1500.0 (scientific)finalとconst
constはfinalより厳格です
var s1 = 'single';
var s2 = "double";
var s3 = '''multi
line string''';
var name = 'Alice';
print('Hi, $name'); // interpolation
print('Length: ${name.length}'); // expression interpolation
var raw = r'No escape: \n'; // raw string (literal)
var escaped = 'It\'s ok'; // escaped quote
print(s1[0]); // 's' (index access)late変数
遅延初期化、最初の使用前に代入する必要があります
bool isTrue = true;
bool isFalse = false;
print(!isTrue); // false
print(isTrue && isFalse); // false
print(isTrue || isFalse); // true
// Only bool is allowed in conditions; no truthy/falsy
// if (1) {} // ERROR: must be bool
if ('text'.isNotEmpty) {
print('non-empty');
}dynamic型
型チェックを無効にします、注意して使用してください
var list = [1, 2, 3];
var typed = <String>['a', 'b'];
var constList = const [1, 2, 3];
list.add(4);
list.addAll([5, 6]);
print(list.length); // 6
print(list[0]); // 1
print(list.sublist(1, 3)); // [2, 3]
var spread = [...list, 7]; // spread
// constList.add(0); // ERROR: immutable定数コンストラクタ
constコンストラクタを使用してコンパイル時定数を作成
var map = {
'name': 'Alice',
'age': 30,
};
var typed = <String, int>{'a': 1, 'b': 2};
map['city'] = 'NYC'; // add entry
print(map['name']); // Alice
print(map.length); // 3
print(map.containsKey('age')); // true
map.forEach((k, v) => print('$k: $v'));
var keys = map.keys.toList(); // [name, age, city]Sets & Runes
Sets are unordered collections of unique elements—useful for deduplication and set operations (union, intersection, difference). Runes expose the Unicode code points of a string, which is needed for emoji and non-BMP characters stored as surrogate pairs in UTF-16.
var set = {1, 2, 3};
set.add(2); // no duplicate added
set.add(4);
print(set); // {1, 2, 3, 4}
print(set.contains(2)); // true
print(set.intersection({2, 3, 5})); // {2, 3}
// Runes (Unicode code points)
var heart = '♥'; // ♥
print(heart); // ♥
print('A'.codeUnitAt(0)); // 65データ型
数値型
numはintとdoubleのスーパータイプです
print(5 + 3); // 8
print(5 - 3); // 2
print(5 * 3); // 15
print(5 / 3); // 1.6666... (double)
print(5 ~/ 3); // 1 (integer division)
print(5 % 3); // 2 (modulo)
print(-(5)); // -5 (unary minus)
print(2.toString()); // '2'文字列
単一引用符、二重引用符、三重引用符をサポート
var i = 5;
print(i++); // 5 (postfix: use, then add)
print(i); // 6
print(++i); // 7 (prefix: add, then use)
print(i--); // 7
print(--i); // 5ブール型
trueとfalseの値のみ
print(3 == 3); // true
print(3 != 4); // true
print(3 < 4); // true
print(3 > 4); // false
print(3 <= 3); // true
print(3 >= 4); // false
print('a' == 'a'); // true (content equality)
var l1 = [1, 2];
var l2 = [1, 2];
print(l1 == l2); // false (reference equality)List
他の言語の配列に似ています
bool a = true, b = false;
print(a && b); // false
print(a || b); // true
print(!a); // false
// short-circuit evaluation
bool check() { print('called'); return true; }
false && check(); // check() NOT called
true || check(); // check() NOT calledMap
キーと値のペアのコレクション
Object x = 'hello';
print(x is String); // true
print(x is! int); // true
if (x is String) {
print(x.length); // smart-cast to String
}
Object y = 42;
print((y as int) + 1); // 43 (cast)
// (y as String); // runtime TypeErrorSet
一意の要素の順序なしコレクション
class Builder {
String? name;
int? size;
Builder setName(String n) { name = n; return this; }
Builder setSize(int s) { size = s; return this; }
}
var b = Builder()
..setName('widget')
..setSize(10);
print(b.name); // widget
String? path;
print(path?.length); // null (safe access)
print(path?.length ?? 0); // 0演算子
算術演算子
~/はDartの整数除算演算子です
int score = 85;
if (score >= 90) {
print('A');
} else if (score >= 80) {
print('B');
} else {
print('C');
}
// ternary expression
var grade = score >= 60 ? 'pass' : 'fail';
print(grade); // pass
// if (score) {} // ERROR: condition must be boolインクリメントとデクリメント
前置:演算後に代入、後置:代入後に演算
for (var i = 0; i < 3; i++) {
print(i);
}
var list = ['a', 'b', 'c'];
for (var item in list) {
print(item);
}
// for-in with Map entries
var map = {'x': 1, 'y': 2};
for (var entry in map.entries) {
print('${entry.key}: ${entry.value}');
}型テスト演算子
asは型キャストを行います
var i = 0;
while (i < 3) {
print('while $i');
i++;
}
var j = 0;
do {
print('do $j');
j++;
} while (j < 3);条件式
??はnull合体演算子です
// Classic switch statement
var color = 'red';
switch (color) {
case 'red':
print('stop');
break;
case 'green':
print('go');
break;
default:
print('unknown');
}
// Dart 3 switch expression
String describe(int n) => switch (n) {
0 => 'zero',
1 || 2 => 'small',
>= 3 && <= 10 => 'medium',
_ => 'large',
};
print(describe(5)); // mediumカスケード演算子
..はオブジェクト自体を返す連鎖呼び出しを可能にします
for (var i = 0; i < 5; i++) {
if (i == 2) continue; // skip 2
if (i == 4) break; // stop at 4
print(i); // 0, 1, 3
}
// labels for nested loops
outer:
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
if (i + j > 2) break outer;
print('$i,$j');
}
}assert
assert(condition, message) checks a condition during development. Assertions are enabled in debug mode and removed in production (release) builds. Use them for internal invariants and debugging—not for input validation that must run in production.
void setAge(int age) {
assert(age >= 0, 'age must be non-negative');
// ...
}
assert(1 == 1); // passes in debug
// assert(1 == 2, 'math is broken'); // fails in debug
// Assertions are stripped in release/production builds制御フロー
if-else
条件はbool型である必要があります
// named function with return type
int add(int a, int b) {
return a + b;
}
// functions are first-class objects
int Function(int) makeAdder(int n) {
return (int x) => x + n;
}
var add5 = makeAdder(5);
print(add5(3)); // 8
print(add(2, 3)); // 5forループ
Cスタイルとfor-inをサポート
// single-expression function with =>
int square(int x) => x * x;
String greet(String name) => 'Hi, $name';
// arrow with nullable
String? firstChar(String? s) => s?.isEmpty ?? true ? null : s[0];
print(square(4)); // 16
print(greet('Al')); // Hi, Al
print(firstChar('hi')); // hwhileループ
do-whileは少なくとも1回実行されます
// optional positional params wrapped in []
String greet(String name, [String? title]) {
if (title != null) {
return 'Hello, $title $name';
}
return 'Hello, $name';
}
print(greet('Alice')); // Hello, Alice
print(greet('Bob', 'Dr.')); // Hello, Dr. Bobswitch
Dart 3はswitch式をサポートしています
// named params wrapped in {}, required marks mandatory
void createUser({
required String name,
int age = 0,
String? email,
}) {
print('$name, $age, $email');
}
createUser(name: 'Alice', age: 30);
createUser(name: 'Bob', email: '[email protected]');
// named params are passed by name, order-independentbreakとcontinue
breakはループを終了し、continueはこの反復をスキップします
// default values for optional positional
double calc(double a, [double b = 1.0, double c = 0.0]) {
return a * b + c;
}
// default values for named
void config({String host = 'localhost', int port = 8080}) {
print('$host:$port');
}
print(calc(5)); // 5.0
print(calc(5, 2)); // 10.0
config(port: 3000); // localhost:3000Anonymous Functions & Closures
Anonymous functions (lambdas) have no name and are often assigned to variables or passed as callbacks. Closures capture variables from their enclosing scope and keep them alive. The parameter list can be typed (int a, int b) or untyped (a, b).
// anonymous function assigned to a variable
var multiply = (int a, int b) => a * b;
print(multiply(3, 4)); // 12
// closure capturing a variable
Function counter() {
int count = 0;
return () => ++count;
}
var c = counter();
print(c()); // 1
print(c()); // 2
// used as callbacks
[1, 2, 3].forEach((n) => print(n));関数
関数宣言
Dartでは、関数は第一級オブジェクトです
class Person {
String name;
int age;
// constructor
Person(this.name, this.age);
void greet() {
print('Hi, I am $name');
}
}
var p = Person('Alice', 30);
p.greet(); // Hi, I am Alice
print(p.name); // Aliceアロー関数
=>は単一式の関数に使用されます
class Point {
double x;
double y;
Point(this.x, this.y);
double distanceTo(Point other) {
return ((x - other.x) * (x - other.x) +
(y - other.y) * (y - other.y));
}
void moveBy(double dx, double dy) {
this.x += dx; // 'this' is optional when unambiguous
y += dy;
}
}オプションパラメータ
[]は位置指定オプションパラメータを囲みます
class Rectangle {
double width, height;
Rectangle(this.width, this.height);
// computed getter
double get area => width * height;
set size(double v) {
width = v;
height = v;
}
}
var r = Rectangle(3, 4);
print(r.area); // 12 (accessed like a field)
r.size = 10;
print(r.area); // 100名前付きパラメータ
{}は名前付きパラメータを囲み、requiredは必須を示します
class MathUtils {
static const double PI = 3.14159;
static double circleArea(double r) => PI * r * r;
}
// accessed via the class, not an instance
print(MathUtils.PI); // 3.14159
print(MathUtils.circleArea(2)); // 12.566
// static members belong to the class, not instancesデフォルト値
オプションパラメータはデフォルト値を持てます
class Logger {
final String name;
static final Map<String, Logger> _cache = {};
// factory may return a cached instance
factory Logger(String name) {
return _cache.putIfAbsent(name, () => Logger._internal(name));
}
Logger._internal(this.name);
}
var a = Logger('app');
var b = Logger('app');
print(identical(a, b)); // true (same cached instance)匿名関数
匿名関数はコールバックとしてよく使用されます
class Book {
String title;
Book(this.title);
@override
String toString() => 'Book($title)';
@override
bool operator ==(Object other) =>
other is Book && other.title == title;
@override
int get hashCode => title.hashCode;
}
print(Book('Dart')); // Book(Dart)
print(Book('A') == Book('A')); // trueクラス
クラス定義
コンストラクタはクラスと同じ名前を持ちます
class Animal {
String species;
// generative constructor
Animal(this.species);
// if no constructor is written, Dart provides:
// Animal() : species = 'unknown';
}
var a = Animal('cat');
print(a.species); // cat名前付きコンストラクタ
クラスは複数の名前付きコンストラクタを持てます
class Point {
double x, y;
Point(this.x, this.y);
// named constructor
Point.origin() : x = 0, y = 0;
Point.fromList(List<double> l) : x = l[0], y = l[1];
}
var p1 = Point.origin();
var p2 = Point.fromList([3, 4]);
print('${p1.x},${p1.y}'); // 0.0,0.0
print('${p2.x},${p2.y}'); // 3.0,4.0ゲッターとセッター
get/setキーワードを使用
class Temperature {
final double celsius;
// initializer list runs before body
Temperature(double c) : celsius = c;
Temperature.fromFahrenheit(double f)
: celsius = (f - 32) * 5 / 9;
// assert in initializer list
Temperature.clamped(double c)
: assert(c >= -273.15),
celsius = c < -273.15 ? -273.15 : c;
}
print(Temperature.fromFahrenheit(32).celsius); // 0.0静的メンバ
staticメンバはクラスに属し、インスタンスには属しません
class Point {
double x, y;
Point(this.x, this.y);
// redirect to another constructor with 'this'
Point.alongX(double x) : this(x, 0);
Point.origin() : this(0, 0);
Point.fromDouble(double n) : this.alongX(n);
}
print(Point.alongX(5).y); // 0.0
print(Point.origin().x); // 0.0ファクトリコンストラクタ
factoryは常に新しいインスタンスを作成するとは限りません
class ImmutablePoint {
final double x;
final double y;
// const constructor: creates compile-time constant instances
const ImmutablePoint(this.x, this.y);
static const origin = ImmutablePoint(0, 0);
}
const p = ImmutablePoint(1, 2);
const o = ImmutablePoint.origin;
print(identical(o, ImmutablePoint(0, 0))); // trueFactory & Caching
Factory constructors can return const or cached instances and may use Dart 3 switch expressions. They differ from generative constructors which always create a new instance. Use factories when construction logic must choose what to return.
class Shape {
final String type;
const Shape._(this.type);
factory Shape(String kind) {
return switch (kind) {
'circle' => const Shape._('circle'),
'square' => const Shape._('square'),
_ => const Shape._('unknown'),
};
}
}
print(Shape('circle').type); // circle
print(identical(Shape('circle'), Shape('circle'))); // true継承
extends継承
Dartは単一継承です
class Animal {
String name;
Animal(this.name);
void speak() => print('$name makes a sound');
}
class Dog extends Animal {
Dog(String name) : super(name);
@override
void speak() => print('$name barks');
}
var d = Dog('Rex');
d.speak(); // Rex barkssuper呼び出し
@overrideはメソッドのオーバーライドを示します
class Vehicle {
int speed = 0;
void accelerate(int by) => speed += by;
void describe() => print('Vehicle at $speed');
}
class Car extends Vehicle {
@override
void accelerate(int by) {
super.accelerate(by); // call parent method
print('Car now at $speed');
}
}
Car().accelerate(10); // Car now at 10抽象クラス
抽象クラスはインスタンス化できません
class Base {
String tag;
Base(this.tag) {
print('Base created: $tag');
}
}
class Derived extends Base {
Derived(String tag) : super(tag) {
print('Derived created');
}
}
// order: super initializer -> super body -> derived body
Derived('x');
// Base created: x
// Derived createdインターフェース実装
すべてのクラスは暗黙的にインターフェースを定義します
class Proxy implements Object {
@override
dynamic noSuchMethod(Invocation inv) {
print('Called: ${inv.memberName}');
return null;
}
}
var p = Proxy();
p.someMissingMethod(); // Called: Symbol("someMissingMethod")noSuchMethod
存在しないメソッドへの呼び出しを処理します
sealed class Shape {
const Shape();
}
class Circle extends Shape {
final double r;
const Circle(this.r);
}
class Square extends Shape {
final double s;
const Square(this.s);
}
// switch is exhaustive over sealed subtypes
double area(Shape s) => switch (s) {
Circle(:var r) => 3.14 * r * r,
Square(:var s) => s * s,
};
print(area(const Circle(2))); // 12.56Mixin
Mixinの定義
mixinはコン ストラクタを持てません
abstract class Animal {
// abstract method: no body, must be overridden
void makeSound();
// concrete method: inherited as-is
void breathe() => print('breathing');
}
class Cat extends Animal {
@override
void makeSound() => print('meow');
}
var c = Cat();
c.makeSound(); // meow
// Animal(); // ERROR: cannot instantiate abstract classMixinの使用
withキーワードを使用して複数のmixinを使用
class Television {
void turnOn() => print('on');
void turnOff() => print('off');
}
// every class implicitly defines an interface
class SmartTV implements Television {
@override
void turnOn() => print('smart on');
@override
void turnOff() => print('smart off');
}
SmartTV().turnOn(); // smart onmixin制約
onはmixinを特定のクラスに制約します
abstract class Flyer {
void fly();
}
abstract class Swimmer {
void swim();
}
// implement multiple interfaces
class Duck implements Flyer, Swimmer {
@override
void fly() => print('flying');
@override
void swim() => print('swimming');
}
Duck().fly(); // flying
Duck().swim(); // swimmingmixin class
Dart 3はmixin classをサポートしています
class Base {
void greet() => print('hello');
void wave() => print('waving');
}
// extends: reuse implementation, single parent
class A extends Base {
@override
void greet() => print('A says hi');
}
// implements: contract only, must override all
class B implements Base {
@override
void greet() => print('B says hi');
@override
void wave() => print('B waving');
}Abstract vs Interface Guidelines
Use abstract classes to share implementation among closely related types (inheritance of code). Use interfaces (abstract classes used via implements) to define capabilities or contracts that unrelated types can fulfill. Dart merges these concepts: an abstract class can serve as both.
// Abstract class: share code among related types
abstract class Repository<T> {
T? find(int id); // abstract
void save(T item) => print('saved'); // shared
}
// Interface: define a capability
abstract class Comparable<T> {
int compareTo(T other);
}
class Product extends Repository<Product>
implements Comparable<Product> {
@override
Product? find(int id) => null;
@override
int compareTo(Product other) => 0;
}Async/Await
async関数
asyncは非同期関数を示し、Futureを返します
mixin Greeter {
String get name;
void greet() => print('Hello, $name!');
}
class User with Greeter {
@override
String name;
User(this.name);
}
User('Alice').greet(); // Hello, Alice!await
awaitはasync関数内でのみ使用できます
mixin Walker {
void walk() => print('walking');
}
mixin Talker {
void talk() => print('talking');
}
// mix in multiple mixins
class Person extends Object with Walker, Talker {
String name;
Person(this.name);
}
var p = Person('Bob');
p.walk(); // walking
p.talk(); // talkingtry-catch非同期
非同期エラーはtry-catchで捕捉します
mixin Musician on Performer {
void playNote() => print('playing note');
}
abstract class Performer {
void perform();
}
class Singer extends Performer with Musician {
@override
void perform() => print('singing');
}
Singer().playNote(); // playing note
// Musician can only be mixed into Performer subtypesFuture.wait並列
複数のFutureを並列実行
// 'mixin class' can be both extended and mixed in
mixin class Counter {
int _count = 0;
int get count => _count;
void increment() => _count++;
}
class App extends Counter {}
class Tool with Counter {}
print(App().count); // 0
App().increment();
Tool().increment();
print(App().count); // 0 (separate instance)async forループ
await forはStreamを消費します
mixin A {
void hello() => print('A');
}
mixin B {
void hello() => print('B');
}
class X with A, B {}
class Y with B, A {}
X().hello(); // B (later mixin wins)
Y().hello(); // A (later mixin wins)
// resolution order: class -> last mixin -> ... -> first mixinStream
Streamの作成
async*はStreamを作成し、yieldは値を送出します
class Stack<T> {
final List<T> _items = [];
void push(T item) => _items.add(item);
T pop() => _items.removeLast();
bool get isEmpty => _items.isEmpty;
}
var s = Stack<int>();
s.push(1);
s.push(2);
print(s.pop()); // 2
var names = Stack<String>();
names.push('Al');Streamのリッスン
listenはStreamSubscriptionを返します
// generic method with its own type parameter
T firstOrDefault<T>(List<T> list, T defaultValue) {
return list.isEmpty ? defaultValue : list.first;
}
print(firstOrDefault<int>([1, 2, 3], 0)); // 1
print(firstOrDefault([], 'none')); // none (type inferred)
// type often inferred from argumentsStreamメソッド
Streamは様々な便利なメソッドを提供します
class Comparable<T> {
int compareTo(T other);
}
// constrain T to subtypes of Comparable<T>
T max<T extends Comparable<T>>(T a, T b) {
return a.compareTo(b) >= 0 ? a : b;
}
// number sum constraint
num sum<T extends num>(List<T> nums) =>
nums.fold(0, (a, b) => a + b);
print(sum([1, 2.5, 3])); // 6.5StreamController
Streamのデータフローを手動制御
List<int> nums = [1, 2, 3];
Map<String, int> scores = {'a': 1, 'b': 2};
Set<double> uniq = {1.1, 2.2, 1.1};
// runtime type checks work (reified generics)
print(nums is List<int>); // true
print(nums is List<String>); // false
print(scores is Map); // true
// generic variance
void process(List<num> list) => print(list);
process(nums); // OK: int is a numStream変換
Listの連鎖操作に似ています
// generic function type alias
typedef Transformer<T> = T Function(T input);
int doubler(int x) => x * 2;
String upper(String s) => s.toUpperCase();
Transformer<int> dt = doubler;
Transformer<String> ut = upper;
print(dt(5)); // 10
print(ut('hi')); // HI
// generic class alias
typedef IntList = List<int>;
IntList xs = [1, 2, 3];Future
Futureの作成
Futureは非同期結果を表します
var nums = [3, 1, 2];
nums.sort();
print(nums); // [1, 2, 3]
print(nums.reversed.toList()); // [3, 2, 1]
print(nums.indexOf(2)); // 1
print(nums.contains(3));// true
print(nums.where((n) => n > 1).toList()); // [2, 3]
print(nums.map((n) => n * 2).toList()); // [2, 4, 6]
print(nums.fold(0, (a, b) => a + b)); // 6thenチェーン
thenは新しいFutureを返します
var a = {1, 2, 3};
var b = {2, 3, 4};
print(a.union(b)); // {1, 2, 3, 4}
print(a.intersection(b)); // {2, 3}
print(a.difference(b)); // {1}
var dedup = [1, 1, 2, 3, 3].toSet();
print(dedup.toList()); // [1, 2, 3]
print(dedup.contains(2)); // trueFuture.delayed
遅延実行
var ages = {'Alice': 30, 'Bob': 25};
ages['Carol'] = 28;
print(ages.keys); // (Alice, Bob, Carol)
print(ages.values); // (30, 25, 28)
print(ages.length); // 3
ages.update('Bob', (v) => v + 1);
print(ages['Bob']); // 26
ages.remove('Alice');
ages.forEach((k, v) => print('$k=$v'));
var mapped = ages.map((k, v) => MapEntry(k, v + 100));Future.any
最初に完了したFutureの結果を返します
var a = [1, 2];
var b = [0, ...a, 3]; // [0, 1, 2, 3]
print(b);
List<int>? maybe;
var c = [0, ...?maybe, 4]; // [0, 4] (null-spread is safe)
print(c);
var m1 = {'a': 1};
var m2 = {'b': 2, ...m1}; // {b: 2, a: 1}
print(m2);Completer
Futureを手動で完了
var promo = true;
var menu = [
'home',
'products',
if (promo) 'sale',
'about',
];
print(menu); // [home, products, sale, about]
var nums = [1, 2, 3];
var doubled = [
for (var n in nums) n * 2,
];
print(doubled); // [2, 4, 6]
// combine: [for (var x in xs) if (x > 0) x]Higher-order Methods
Lists/Iterables support any, every, firstWhere, reduce, fold, skip, take, expand, and more. fold is powerful—it carries an accumulator of any type. These higher-order methods enable declarative, functional-style data processing without explicit loops.
var nums = [1, 2, 3, 4, 5];
print(nums.any((n) => n > 4)); // true
print(nums.every((n) => n > 0)); // true
print(nums.firstWhere((n) => n > 2)); // 3
print(nums.reduce((a, b) => a + b)); // 15
var byParity = nums.fold(<bool, List<int>>{}, (m, n) {
m[n.isOdd] = [...?m[n.isOdd], n]; return m;
});
print(byParity); // {true: [1,3,5], false: [2,4]}コレクション
List操作
Listは重複を許す順序付きコレクションです
Future<String> fetchUser() {
return Future.delayed(Duration(seconds: 1), () => 'Alice');
}
void main() {
fetchUser().then((name) {
print('Got: $name'); // Got: Alice (after 1s)
});
print('waiting...');
}Set操作
Setは一意の要素の順序なしコレクションです
Future<String> fetchUser() async {
await Future.delayed(Duration(seconds: 1));
return 'Alice';
}
Future<void> main() async {
print('start');
String name = await fetchUser();
print('Got: $name');
print('done');
}Map操作
Mapはキーと値のペアのコレクションです
Future<int> divide(int a, int b) async {
if (b == 0) throw Exception('divide by zero');
return a ~/ b;
}
Future<void> main() async {
try {
var result = await divide(10, 0);
print(result);
} catch (e) {
print('Error: $e'); // Error: Exception: divide by zero
} finally {
print('done');
}
}コレクションスプレッド
...スプレッド演算子
Future<int> compute() async => 42;
compute()
.then((v) => v * 2)
.then((v) => print(v)) // 84
.catchError((e) => print('err: $e'))
.whenComplete(() => print('cleanup'));
// chaining transforms the result type
Future<String> fetch() async => 'data';
fetch().then((s) => s.length).then(print); // 4collection-ifとcollection-for
Dart固有のコレクション内条件/ループ
Future<int> task(int n) async {
await Future.delayed(Duration(milliseconds: n));
return n;
}
// run in parallel, wait for all
var all = await Future.wait([task(100), task(50), task(200)]);
print(all); // [100, 50, 200]
// resolve with the first to complete
var first = await Future.any([task(100), task(50), task(200)]);
print(first); // 50 (fastest)Completer
A Completer lets you manually create and complete a Future. Call complete(value) or completeError(error) to finish it. Completers are useful when wrapping callback-based APIs into Futures, or when a Future's completion is triggered by an external event you control.
import 'dart:async';
Completer<String> completer = Completer<String>();
// complete the future from elsewhere
Future<String> get value => completer.future;
completer.complete('resolved!');
void main() async {
print(await value); // resolved!
}
// useful when bridging callback-based APIs to Futures文字列メソッド
文字列補間
$variableまたは${expression}
Stream<int> countDown(int from) async* {
while (from > 0) {
await Future.delayed(Duration(seconds: 1));
yield from;
from--;
}
}
void main() async {
await for (var n in countDown(3)) {
print(n); // 3, 2, 1 (one per second)
}
}一般的なメソッド
文字列は不変です
var sub = countDown(3).listen(
(n) => print('got $n'),
onDone: () => print('done'),
onError: (e) => print('err: $e'),
);
// pause/resume/cancel
sub.pause();
sub.resume();
// sub.cancel(); // stop listening
Stream<int> countDown(int from) async* {
while (from > 0) yield from--;
}部分文字列
インデックスは0から始まります
var stream = Stream.fromIterable([1, 2, 3, 4]);
// transform like an Iterable
var evens = stream.where((n) => n.isEven);
var doubled = stream.map((n) => n * 2);
await for (var n in Stream.fromIterable([1,2,3]).map((n) => n * 10)) {
print(n); // 10, 20, 30
}
print(await stream.first); // 1
print(await stream.last); // 4
print(await stream.length); // 4置換と分割
正規表現置換をサポート
import 'dart:async';
var controller = StreamController<int>();
// add events manually
controller.add(1);
controller.add(2);
controller.addError('oops');
controller.close();
controller.stream.listen(
(n) => print(n), // 1, 2
onError: (e) => print(e), // oops
onDone: () => print('done'),
);
// use controller.addError/sink.add for errors