Dart vs Swift

| 作者 : Andrea Bizzotto
| 原文 : [medium](https://medium.com/coding-with-flutter/dart-vs-swift-a-comparison-6491e945dc17)
| 翻訳 : [jamestong](https://qiita.com/jamestong)
| 校正 : [jamestong](https://qiita.com/jamestong)

DartとSwiftは私のお気に入りの2つのプログラミング言語です。私は商用およびオープンソースのコードでこれらを幅広く使用してきました。

この記事では、DartとSwiftを並べて比較してみます。

- 両者の違いを強調する;
- 開発者の参考として、一方の言語から他方の言語に移行する（または両方を使用する）時の注意点を挙げる。


背景：

- Dartは、単一のコードベースから美しいネイティブアプリを構築するためのGoogleのフレームワークであるFlutterに対応している;
- Swiftは、iOS、macOS、tvOS、watchOSにまたがるAppleのSDKをサポートしている。


以下は、両言語の主な機能（`Dart 2.1`と`Swift 4.2`の時点で）を比較したものです。各機能の詳細な議論はこの記事の範囲を超えているので、必要に応じて両言語の参考文献を参考してください。

##目次
- 対照表
- 変数
- 型推論
- 可変型/不可変型変数
- 関数
- 名前付きパラメータと名前なしパラメータ
- オプションとデフォルトのパラメータ
- クロージャ
- タプル
- 制御フロー
- コレクション（**arrays, sets, maps**)
- Nullability & Optionals
- クラス
- 継承
- プロパティー
- プロトコル / 抽象クラス
- Mixins
- 拡張
- 列挙型
- 構造体
- エラー処理
- ジェネリクス
- アクセス制御
- 非同期プログラミング:`Futures`
- 非同期プログラミング:`Streams`
- メモリ管理
- コンパイルと実行
- その他の機能
- Dartに欠けている私のお気に入りのSwiftの機能
- Swiftに欠けている私のお気に入りのDartの機能
- 結論

##対照表

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678085/8cec4b63-914d-8bc2-d863-9042f61e93ac.png)

##変数

変数**宣言**の構文は、Dartでは次のように:

```dart:
String name;
int age;
double height;
```

Swiftではこのように:

```swift:
var name: String
var age: Int
var height: Double
```

変数の**初期化**はDartではこのように:

```dart:
var name = 'Andrea';
var age = 34;
var height = 1.84;
```

Swiftではこのように:

```swift:
var name = "Andrea"
var age = 34
var height = 1.84
```

上記らの例では、型のアノテーションは必要ありません。これは、どちらの言語も代入の右側の式から型を推測できるからです。

##型推論
型推論とは、Dartで次のように書けるということです。

```dart:
var arguments = {'argA': 'hello', 'argB': 42}; // Map<String, Object>
```

そして、`arguments`の型はコンパイラによって自動的に解決されます。

Swiftでは、同じように書くことができます:

```swift:
var arguments = [ "argA": "hello", "argB": 42 ] // [ String : Any ]
```

###さらに
Dartのドキュメントを引用します。
>解析器は、フィールド、メソッド、ローカル変数、およびほとんどのジェネリック引数の型を推論することができます。解析器が特定の型を推論するのに十分な情報を持っていない場合は、動的型付け`dynamic`を使います。

そしてSwiftの場合は:
>Swiftは広範囲に型推論を使用しており、コード中の多くの変数や式の型や型の一部を省略することができます。例えば、`var x: Int = 0`のように書くことではなく, `var x = 0`のように書けば、 コンパイラは x が `Int` 型の値を指定していることを正しく推論します。

####動的型付け
任意の型を持つ変数は、Dartでは`dynamic`キーワード、Swiftでは`Any`キーワードで宣言されます。

動的型付けはJSONなどのデータを読み込むときによく使われます。

##可変型/不変型変数
変数は、可変なものと不変なものを宣言することができます。

可変な変数を宣言するには、両言語とも `var` キーワードを使用します。

```swift
var a = 10; // int (Dart)
a = 20; // ok
var a = 10 // Int (Swift)
a = 20 // ok
```

不変変数の宣言には、Dartでは`final`、Swiftでは`let`を使います。

```swift
final a = 10;
a = 20; // 'a': a final variable, can only be set once.
let a = 10
a = 20 // Cannot assign to value: 'a' is a 'let' constant
```

注意：Dartのドキュメントでは、`final`と`const`という2つのキーワードが定義されていますが、これらは以下のように動作します。
>変数を変更するつもりがない場合は、`var`の代わりに、または型に加えて、`final`または`const`を使用してください。`final`変数は一度だけ設定することができ、`const`変数はコンパイル時の定数です。(`const`変数は暗黙のうちに`final`になります。) finalのトップレベル変数やクラス変数は、初めて使用されたときに初期化されます。

さらに

>`final`はシングルアサインメントを意味します。最終的な変数やフィールドには`initializer`が必要です。一度値が代入されると、`final`変数の値を変更することはできません。

TL;DR: Dartで不変変数を定義するには**final**を使います。

Swiftでは`let`で定数を宣言します。
>定数の宣言は、定数の値をプログラムに導入します。定数は`let`キーワードを使って宣言され、以下のような形式になります。

```swift
let constant name: type = expression
```

>定数の宣言は、定数名とイニシャライザ式の値との間の不変の結合を定義します。
定数の値が設定された後は変更できません。


##関数
関数はSwiftとDartの中では一等市民です。

これはオブジェクトと同じように、関数は引数として渡されたり、プロパティとして保存されたり、結果として返されたりすることができることを意味します。

最初の比較として、引数のない関数の宣言方法を見てみましょう。

Dartでは、メソッド名の前にリターンタイプが付きます。

```dart
void foo();
int bar();
```

Swift では、サフィックスとして `-> T` 記法を使用しています。戻り値がない場合(Void)にはそれを付く必要がありません。

```swift
func foo()
func bar() -> Int
```

##名前付きパラメータと名前なしパラメータ
どちらの言語も名前付きと名前なしのパラメータをサポートしています。

Swiftでは、パラメータはデフォルトで名前が付けられています。

```swift
func foo(name: String, age: Int, height: Double)
foo(name: "Andrea", age: 34, height: 1.84)
```

Dartでは、中括弧(**{ }**)で名前付きパラメータを定義します。

```dart
void foo({String name, int age, double height});
foo(name: 'Andrea', age: 34, height: 1.84);
```

Swiftでは、外部パラメータとしてアンダースコア(_)を使って名前のないパラメータを定義します。

```swift
func foo(_ name: String, _ age: Int, _ height: Double)
foo("Andrea", 34, 1.84)
```

Dartでは、中括弧(**{ }**)を省略して名前のないパラメータを定義します。

```dart
void foo(String name, int age, double height);
foo('Andrea', 34, 1.84);
```


##オプションとデフォルトのパラメータ
どちらの言語もデフォルトのパラメータをサポートしています。

>Swiftでは、パラメータの型の後にパラメータに値を割り当てることで、関数内の任意のパラメータのデフォルト値を定義することができます。デフォルト値が定義されている場合、関数を呼び出す際にそのパラメータを省略することができます。

```swift
func foo(name: String, age: Int = 0, height: Double = 0.0) 
foo(name: "Andrea", age: 34) // name: "Andrea", age: 34, height: 0.0
```

Dartでは、オプションのパラメータは位置指定か名前指定のどちらかを指定することができますが、両方を指定することはできません。

```dart
// positional optional parameters
void foo(String name, [int age = 0, double height = 0.0]);
foo('Andrea', 34); // name: 'Andrea', age: 34, height: 0.0
// named optional parameters
void foo({String name, int age = 0, double height = 0.0});
foo(name: 'Andrea', age: 34); // name: 'Andrea', age: 34, height: 0.0
```

##クロージャ
一級オブジェクトである関数は、他の関数の引数として渡されたり、変数に代入されたりすることができます。

この文脈では、関数はクロージャ`closure`としても呼ばれています。

ここでは、各項目のインデックスと内容を表示するためにクロージャを使用して、項目のリストを反復処理する関数のDartの例を示します。

```dart
final list = ['apples', 'bananas', 'oranges'];
list.forEach((item) => print('${list.indexOf(item)}: $item'));
```

クロージャは1つの引数(`item`)を取り、その`item`のインデックスと値を表示するが、リターンしません。

矢印表記 (`=>`) を使用していることに注意してください。これは中括弧の中にある単一の`return`文の代わりに使うことができます。

```dart
list.forEach((item) { print('${list.indexOf(item)}: $item'); });
```

Swiftでは同じコードは次のようになります。

```dart
let list = ["apples", "bananas", "oranges"]
list.forEach({print("\(String(describing: list.firstIndex(of: $0))) \($0)")})
```

この場合、クロージャに渡される引数の名前は指定せず、代わりに `$0` を使用して最初の引数を意味します。これは完全にオプションであり、必要に応じて名前付きのパラメータを使用することもできます。

```swift
list.forEach({ item in print("\(String(describing: list.firstIndex(of: item))) \(item)")})
```

Swiftでは非同期コードの補完ブロックとしてクロージャがよく使われます。


##タプル
Swiftドキュメントより:

>タプルは複数の値を1つの複合値にまとめます。タプル内の値は任意の型をとることができ、互いに同じ型である必要はありません。

これらは小型の軽量型として使用することができ、複数の戻り値を持つ関数を定義する際に便利です。

Swiftでのタプルの使い方:

```swift
let t = ("Andrea", 34, 1.84)
print(t.0) // prints "Andrea"
print(t.1) // prints 34
print(t.2) // prints 1.84
```

Dartでは[サードパーティパッケージ](https://pub.dev/packages/tuple)でタプルを実現出来ます。

```dart
const t = const Tuple3<String, int, double>('Andrea', 34, 1.84);
print(t.item1); // prints 'Andrea'
print(t.item2); // prints 34
print(t.item3); // prints 1.84
```

##制御フロー
どちらの言語も様々な制御フロー文を提供しています。

例としては、**if** 条件文、**for** ループ、**while** ループ、**switch**文などがあります。

これらをここで説明するとかなり長くなるので、公式ドキュメントを参照してください。


##コレクション（**arrays, sets, maps**)

###Arrays / Lists
配列はオブジェクトの順序付けされたグループです。

Dartでは`List`で配列`Arrays`を作ることができます。

```dart
var emptyList = <int>[]; // empty list
var list = [1, 2, 3]; // list literal
list.length; // 3
list[1]; // 2
```

Swiftでの配列は組み込み型です。

```swift
var emptyArray = [Int]() // empty array
var array = [1, 2, 3] // array literal
array.count // 3
array[1] // 2
```

###Sets
Swiftのドキュメントより：
>Setは、定義された順序を持たないコレクションの中に、同じ型の異なる値を格納します。アイテムの順序が重要ではない場合や、アイテムが一度しか表示されないようにする必要がある場合には、配列の代わりにセットを使うことができます。

DartのSet クラスはこのように定義されています。

```dart
var emptyFruits = <String>{}; // empty set literal
var fruits = {'apple', 'banana'}; // set literal
```

同様に、Swiftは:

```swift
var emptyFruits = Set<String>()
var fruits = Set<String>(["apple", "banana"])
```

###Maps / Dictionaries
Swiftのドキュメントには、`map/dictionary`に対し良い定義があります。

>辞書は、同じ型のキーと同じ型の値の間の関連付けを、定義された順序を持たないコレクションに格納します。各値は唯一のキーに関連付けられ、辞書内でその値の識別子として機能します。

Dartは`map`を次のように定義しています。

```dart
var namesOfIntegers = Map<Int,String>(); // empty map
var airports = { 'YYZ': 'Toronto Pearson', 'DUB': 'Dublin' }; // map literal
```

Swiftでは`map`を辞書`dictionary`と呼びます。

```swift
var namesOfIntegers = [Int: String]() // empty dictionary
var airports = ["YYZ": "Toronto Pearson", "DUB": "Dublin"] // dictionary literal
```

##Nullability & Optionals
Dartでは、どんなオブジェクトでも`null`にすることができます。そして、`null` オブジェクトのメソッドや変数にアクセスしようとすると、`null`ポインタ例外が発生します。これは、コンピュータプログラムで最も一般的なエラーの原因の一つです（最も一般的ではないにしても）。

最初から、Swiftにはオブジェクトが値を持てるか持てないかを宣言するための組み込みの言語機能であるオプショナルがありました。ドキュメントを引用します。

>値が存在しないかもしれない状況では、オプショナル`Optional`を使用します。オプショナルは2つの可能性を表します。値があり、その値にアクセスするためにオプションをアンラップすることができる場合と、値が全く存在しない場合です。

これとは対照的に、非オプショナル変数を使用することで、常に値を持つことを保証できます。

```swift
var x: Int? // optional
var y: Int = 1 // non-optional, must be initialized
```

ノート:Swiftの変数がオプショナルであると言うことは、Dartの変数がnullになる可能性があると言うこととほぼ同じです。

言語レベルでオプショナルをサポートしていない場合、変数が`null`であるかどうかを実行時にチェックすることしかできません。

オプショナルを使うと、コンパイル時に情報をエンコードします。オプショナルをアンラップすることで、値を保持しているかどうかを安全にチェックすることができます。

```swift
func showOptional(x: Int?) {
  // use `guard let` rather than `if let` as best practice
  if let x = x { // unwrap optional
    print(x)
  } else {
    print("no value")
  }
}
showOptional(x: nil) // prints "no value"
showOptional(x: 5) // prints "5"
```

そして、変数が値を持たなければならないことがわかっている場合は、非オプショナル`non-optional`を使うことができます。

```swift
func showNonOptional(x: Int) {
  print(x)
}
showNonOptional(x: nil) // [compile error] Nil is not compatible with expected argument type 'Int'
showNonOptional(x: 5) // prints "5"
```

上の最初の例は、Dartではこのように実装することができます。

```dart
void showOptional(int x) {
  if (x != null) {
    print(x);
  } else {
    print('no value');
  }
}
showOptional(null) // prints "no value"
showOptional(5) // prints "5"
```

そして2個目はこんな感じ:

```dart
void showNonOptional(int x) {
  assert(x != null);
  print(x); 	
}
showNonOptional(null) // [runtime error] Uncaught exception: Assertion failed
showNonOptional(5) // prints "5"
```

オプショナルを持つことは、実行時ではなくコンパイル時にエラーをキャッチできることを意味します。そして、エラーを早期にキャッチすることで、より安全でバグの少ないコードを作ることができます。

Dart はオプショナルをサポートしていませんが、アサーション (および名前付きパラメータの `@required` **アノテーション**) を使用することでなんとか緩和されています。

これらのアサーションは `Flutter SDK` で広く使われていますが、結果的には、余計の定型的なコードが生じます。

##クラス
クラスはオブジェクト指向言語でプログラムを書くための主要な構成要素です。

クラスは Dart と Swiftが両方ともサポートしていますが、いくつかの違いがあります。

###構文

Swiftの`initializer`と3つのメンバ変数を持つクラスです。

```swift
class Person {
  let name: String
  let age: Int
  let height: Double
  init(name: String, age: Int, height: Double) {
    self.name = name
    self.age = age
    self.height = height
  }
}
```

Dartも同じように：

```dart
class Person {
  Person({this.name, this.age, this.height});
  final String name;
  final int age;
  final double height;
}
```

Dart のコンストラクタで `this.[propertyName]` を使用することに注意してください。これは、コンストラクタが実行される前にインスタンスのメンバ変数を設定するための糖衣構文`syntactic sugar`です。

###ファクトリ コンストラクタ

Dartでは、ファクトリ・コンストラクタを作成することができます。
>常にクラスの新しいインスタンスを生成しないコンストラクタを実装する場合は `factory` キーワードを使用します。

ファクトリコンストラクタの実用的な使用例としては、JSONからモデルクラスを作成する場合に使われます。

```dart
class Person {
  Person({this.name, this.age, this.height});
  final String name;
  final int age;
  final double height;
  factory Person.fromJSON(Map<dynamic, dynamic> json) {
    String name = json['name'];
    int age = json['age'];
    double height = json['height'];
    return Person(name: name, age: age, height: height);
  }
}
var p = Person.fromJSON({
  'name': 'Andrea',
  'age': 34,
  'height': 1.84,
});
```

##継承
Swiftはシングル継承モデルを使用しており、どのクラスも1つのスーパークラスしか持っていないことを意味します。Swiftのクラスは複数のインターフェイス（プロトコルとも呼ばれる）を実装することができます。

Dartクラスは`mixin`ベースの継承を持っています。ドキュメントを引用します。

>すべてのオブジェクトは1つのクラスのインスタンスであり、すべてのクラスは`Object`から派生します。`mixin`ベースの継承とは、(Objectを除く)すべてのクラスにはちょうど1つのスーパークラスがありますが、クラス本体は複数のクラス階層で再利用できることを意味します。

Swiftでのシングル継承の動作:

```swift
class Vehicle {
  let wheelCount: Int
  init(wheelCount: Int) {
    self.wheelCount = wheelCount
  }
}
class Bicycle: Vehicle {
  init() {
    super.init(wheelCount: 2)
  }
}
```

Dartは：

```dart
class Vehicle {
  Vehicle({this.wheelCount});
  final int wheelCount;
}
class Bicycle extends Vehicle {
  Bicycle() : super(wheelCount: 2);
}
```

##プロパティー
これらはDartではインスタンス変数と呼ばれ、Swiftでは単にプロパティと呼ばれます。

Swiftでは、保存されたプロパティと計算されたプロパティに区別があります。

```swift
class Circle {
  init(radius: Double) {
    self.radius = radius
  }
  let radius: Double // stored property
  var diameter: Double { // read-only computed property
    return radius * 2.0
  }
}
```

Dartでは、同じような区別があります：

```dart
class Circle {
  Circle({this.radius});
  final double radius; // stored property
  double get diameter => radius * 2.0; // computed property
}
```

計算されたプロパティの`getters`に加えて、`setters`を定義することもできます。

上の例を使って、`diameter`プロパティを`setter`を含むように書き換えることができます。

```swift
var diameter: Double { // computed property
  get {
    return radius * 2.0
  }
  set {
    radius = newValue / 2.0
  }
}
```

Dartでは、このように単独の`setter`を追加することができます。

```dart
set diameter(double value) => radius = value / 2.0;
```

###プロパティオブザーバ

これがSwiftの特徴です。

>プロパティオブザーバーはプロパティの値の変化を観測し、それに反応します。プロパティオブザーバーは、プロパティの値が設定されるたびに、新しい値がプロパティの現在の値と同じであっても呼び出されます。

使い方：

```swift
var diameter: Double { // read-only computed property
  willSet(newDiameter) {
    print("old value: \(diameter), new value: \(newDiameter)")  
  }
  didSet {
    print("old value: \(oldValue), new value: \(diameter)")  
  }
}
```

##プロトコル / 抽象クラス
ここでは、どのように実装されているかを指定せずに、メソッドやプロパティを定義するために使用される構文について説明します。これは他の言語ではインターフェースとして知られています。

Swiftでは、インターフェースをプロトコルと呼ばれています。

```swift

protocol Shape {
  func area() -> Double
}
class Square: Shape {
  let side: Double
  init(side: Double) {
    self.side = side
  }
  func area() -> Double {
    return side * side
  }
}
```

Dartには、抽象クラスとして知られる同様の構成があります。抽象クラスはインスタンス化できません。しかし、実装を持つメソッドを定義することはできます。

上の例は、Dartではこのように書くことができます。

```dart
abstract class Shape {
  double area();
}
class Square extends Shape {
  Square({this.side});
  final double side;
  double area() => side * side;
}
```


##Mixins
Dartでは、`Mixin`は通常のクラスであり、複数のクラス階層で再利用することができます。

先ほど定義した`Person`クラスを`NameExtension mixin`で拡張する方法を紹介します。

```dart
abstract class NameExtension {
  String get name;
  String get uppercaseName => name.toUpperCase();
  String get lowercaseName => name.toLowerCase();
}
class Person with NameExtension {
  Person({this.name, this.age, this.height});
  final String name;
  final int age;
  final double height;	
}
var person = Person(name: 'Andrea', age: 34, height: 1.84);
print(person.uppercaseName); // 'ANDREA'
```

##拡張
拡張機能はSwift言語の1つの特徴です。ドキュメントを引用します。

>拡張機能は既存のクラス、構造体、列挙、またはプロトコルの型に新しい機能を追加します。これには、元のソースコードにアクセスできない型を拡張する機能が含まれます(レトロアクティブモデリング`retroactive modeling`として知られています)。

これは、Dart の mixins ではできません。

上の例を借りて、`Person` クラスを次のように拡張します。

```swift
extension Person {
  var uppercaseName: String {
    return name.uppercased()
  }
  var lowercaseName: String {
    return name.lowercased()
  }
}
var person = Person(name: "Andrea", age: 34, height: 1.84)
print(person.uppercaseName) // "ANDREA"
```

拡張機能にはここで紹介した以上に多くがあり、特にプロトコルやジェネリックと組み合わせて使用される場合には、それ以上に多くのことができます。

拡張機能の最も一般的な使用例の一つは、既存の型にプロトコルに準拠した機能を追加することです。例えば、既存のモデルクラスにシリアライズ機能を追加するために拡張機能を使用することができます。


##列挙型
Dartは、列挙型に対しいくつかの基本的なサポートを持っています。

Swiftの列挙型は、関連する型をサポートしているので、非常に強力です。

```swift
enum NetworkResponse {
  case success(body: Data) 
  case failure(error: Error)
}
```

これにより、このようなロジックを書くことが可能になります。

```swift
switch (response) {
  case .success(let data):
    // do something with (non-optional) data
  case .failure(let error):
    // do something with (non-optional) error
}
```

`data`パラメータと`error`パラメータが相互に排他的であることに注意してください。

Dartでは列挙型に追加の値を関連付けることはできませんので、上記のコードは次のように実装できるかもしれません。

```dart
class NetworkResponse {
  NetworkResponse({this.data, this.error})
  // assertion to make data and error mutually exclusive
  : assert(data != null && error == null || data == null && error != null);
  final Uint8List data;
  final String error;
}
var response = NetworkResponse(data: Uint8List(0), error: null);
if (response.data != null) {
  // use data
} else {
  // use error
}
```

いくつか注意点があります。

- ここではアサーションを使用して、オプショナルがないという事実を補っています。
- コンパイラはすべてのケースをチェックすることはできません。これはレスポンスを処理するプロセスで`switch`を使わないからです。

まとめると、Swiftの列挙型はDartに比べてかなり強力で表現力があります。

`Dart Sealed Unions`のようなサードパーティのライブラリは、Swift列挙型と同様の機能を提供し、ギャップを埋めるのに役立ちます。

##構造体
Swiftでは構造体とクラスを定義することができます。

どちらの構造にも多くの共通点があり、いくつかの違いがあります。

主な違いは:
>クラスは参照型であり、構造体は値型である。

ドキュメントを引用します。
>値型とは、変数や定数に代入されたとき、または関数に渡されたときに値がコピーされる型のことです。  
Swiftでは、構造体と列挙はすべて値型です。これは、作成した構造体と列挙のインスタンス、およびそれらがプロパティとして持つ値型は、コード内で渡されるときに常にコピーされることを意味します。  
値型とは異なり、参照型は変数や定数に代入されたときや関数に渡されたときにはコピーされません。コピーではなく、同じ既存のインスタンスへの参照が使用されます。

これが何を意味するのかを知るために、次の例を考えてみましょう。

```swift
class Person {
  var name: String
  var age: Int
  var height: Double
  init(name: String, age: Int, height: Double) {
    self.name = name
    self.age = age
    self.height = height
  }
}
var a = Person(name: "Andrea", age: 34, height: 1.84)
var b = a
b.age = 35
print(a.age) // prints 35
```

`Person`を構造体`struct`として定義し直すと、こんな感じになります。

```swift
struct Person {
  var name: String
  var age: Int
  var height: Double
  init(name: String, age: Int, height: Double) {
    self.name = name
    self.age = age
    self.height = height
  }
}
var a = Person(name: "Andrea", age: 34, height: 1.84)
var b = a
b.age = 35
print(a.age) // prints 34
```

構造体には、ここで取り上げた以外にも多くのことがあります。
構造体は、Swiftでデータやモデルを扱うために効果的に使うことができ、バグの少ないロバストなコード`robust code`につながります。


##エラー処理
Swiftのドキュメントからの定義:
>エラー処理とは、プログラムのエラー状態に応答して回復するプロセスです。

DartもSwiftもエラーを処理するためのテクニックとして`try/catch`を使用していますが、いくつかの違いがあります。

Dartでは、任意のメソッドは任意の型の例外を投げることができます。

```dart
class BankAccount {
  BankAccount({this.balance});
  double balance;
  void withdraw(double amount) {
    if (amount > balance) {
      throw Exception('Insufficient funds');
    }
    balance -= amount;
  }
}
```

例外は`try/catch`ブロックでキャッチできます。

```dart
var account = BankAccount(balance: 100);
try {
  account.withdraw(50); // ok
  account.withdraw(200); // throws
} catch (e) {
  print(e); // prints 'Exception: Insufficient funds'
}
```

Swiftでは、メソッドが例外を投げることができるときに明示的に宣言します。これは`throws`キーワードで行われ、全てのエラーはエラープロトコルに準拠しなければなりません。

```swift
enum AccountError: Error {
  case insufficientFunds
}
class BankAccount {
  var balance: Double
  init(balance: Double) {
    self.balance = balance
  }
  func withdraw(amount: Double) throws {
    if amount > balance {
      throw AccountError.insufficientFunds
    }
    balance -= amount
  }
}
```

エラーを処理する際には、`do/catch`ブロックの中で`try`キーワードを使用します。

```swift
var account = BankAccount(balance: 100)
do {
  try account.withdraw(amount: 50) // ok
  try account.withdraw(amount: 200) // throws
} catch AccountError.insufficientFunds {
  print("Insufficient Funds")
}
```

`throw`できるメソッドを呼び出す際には、`try`キーワードが必須であることに注意してください。
また、エラー自体は強く型付けされているので、すべての可能なケースをカバーするために複数のキャッチブロックを持つことができます。

**try, try?, try!**

Swiftでは、エラーを扱うためにあまり冗長ではない方法を提供しています。

`do/catch` ブロックを使わずに `try?` を使用し、これにより全ての例外は無視されるようになります。

```swift
var account = BankAccount(balance: 100)
try? account.withdraw(amount: 50) // ok
try? account.withdraw(amount: 200) // fails silently
```

あるいは、あるメソッドはエラーが投げられないことが確実な場合は、`try!`を使用できます。

```swift
var account = BankAccount(balance: 100)
try! account.withdraw(amount: 50) // ok
try! account.withdraw(amount: 200) // crash
```

上の例では、プログラムがクラッシュしてしまいます。したがって、`try!` はプロダクションコードでは推奨されず、テストを書くときに適しています。

全体的に、Swiftにおけるエラー処理の明示的な性質はAPI設計において非常に有益です。メソッドがエラーを投げることができるかどうかを簡単に確認できるからです。

同様に、メソッド呼び出しで `try` を使用すると、投げることができるコードに注意が向けられ、エラーケースを考慮することを余儀なくされます。

この点(エラー処理)では、Swift は Dart よりも安全で堅牢なものになっています。


##ジェネリクス
Swiftのドキュメントを引用します。
>ジェネリクスコードを使うと、定義した要件に従って、どんな型でも動作する柔軟で再利用可能な関数や型を書くことができます。重複を避け、明確で抽象的な方法で意図を表現するコードを書くことができます。

ジェネリクスについて両言語ともサポートしています。

ジェネリクスの最も一般的な使用例の1つは、配列、集合、マップなどのコレクションです。

そして、これらを使って独自の型を定義することができます。Swiftでジェネリクス`Stack`型を定義する方法を以下に示します。

```swift
struct Stack<Element> {
  var items = [Element]()
  mutating func push(_ item: Element) {
    items.append(item)
  }
  mutating func pop() -> Element {
    return items.removeLast()
  }
}
```

同様に、Dartではこう書きます。

```dart
class Stack<Element> {
  var items = <Element>[]
  void push(Element item) {
    items.add(item)
  }
  void pop() -> Element {
    return items.removeLast()
  }
}
```

Swiftのジェネリクスでは非常に便利で強力なもので、プロトコルの型制約や関連する型を定義するために使用することができます。


##アクセス制御

Swiftのドキュメントを引用します。

>アクセス制御は、他のソースファイルやモジュールのコードからコードの一部へのアクセスを制限します。この機能により、コードの実装の詳細を隠したり、そのコードにアクセスして使用できる優先インターフェースを指定したりすることができます。

Swiftには5つのアクセスレベルがあります: `open`、`public`、`internal`、`file-private`、`private`です。

これらはモジュールやソースファイルを扱う際に使用されます。

>モジュールとは、コード配布の単一ユニット、つまりフレームワークやアプリケーションを構築して単一ユニットとして出荷され、Swiftの`import`キーワードで別のモジュールからインポートできるものです。

`open`と`public`アクセスのレベルは、モジュールの外部からコードにアクセスできるます。

`private`および`file-private`のアクセスレベルは、定義されているファイルの外ではコードにアクセスできません。

例：

```swift
public class SomePublicClass {}
internal class SomeInternalClass {}
fileprivate class SomeFilePrivateClass {}
private class SomePrivateClass {}
```

アクセスレベルはDartの方がシンプルで、`public`と`private`に限定されています。

>Javaとは異なり、Dartには`public`、`protected`、`private`というキーワードはありません。識別子がアンダースコア` _ `で始まる場合は、それはプライベートです。

例:

```dart
class HomePage extends StatefulWidget { // public
  @override
  _HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> { ... } // private
```

アクセス制御は、DartとSwiftでは異なる目的で設計されました。その結果、アクセスレベルが大きく異なっています。


##非同期プログラミング:`Futures`
非同期プログラミングはDartが最も得意とする分野です。
以下のようなユースケースを扱う場合、何らかの形の非同期プログラミングが必要になります。

- ウェブからコンテンツをダウンロードする
- バックエンドとの通信
- 長時間稼働する業務を行う

これらのケースでは、実行中のメインスレッドをブロックしない方が良いでしょう。

Dartのドキュメントを引用します。
>非同期操作は、操作が終わるのを待っている間に他の作業を完了させることができます。Dartでは、非同期操作の結果を表現するためにFutureオブジェクトを使用します。`Future`を使用するには、`async/await`または`Future API`を使用します。

例として、非同期プログラミングをどのように使うかを見てみましょう。

- サーバでユーザを認証する
- アクセストークンを格納してストレージを守る
- ユーザープロファイル情報を取得する

Dartでは、これは`Future`と`async/await`の組み合わせで実現できます。

```dart
Future<UserProfile> getUserProfile(UserCredentials credentials) async {
  final accessToken = await networkService.signIn(credentials);
  await secureStorage.storeToken(accessToken, forUserCredentials: credentials);
  return await networkService.getProfile(accessToken);
}
```

Swiftでは、`async/await`というAPIを提供しておらず、クロージャ(補完ブロック)でしか実現できません。

```swift
func getUserProfile(credentials: UserCredentials, completion: (_ result: UserProfile) -> Void) {
  networkService.signIn(credentials) { accessToken in
    secureStorage.storeToken(accessToken) {
      networkService.getProfile(accessToken, completion: completion)
    }
  }
}
```

これは、ネストされた補完(`completion`)ブロックによる「運命のピラミッド(`pyramid of doom`)」につながります。そして、このシナリオではエラー処理が非常に難しくなります。

Dartでは、上記コードのエラーの処理は、`getUserProfile`メソッドに`try/catch`ブロックを追加するだけで済みます。

参考として、将来的にはSwiftに`async/await`を追加するという提案があります。

これが実装されるまでは、開発者はGoogleの`Promises`のようなサードパーティ製のライブラリを使うことができます。

##非同期プログラミング:`Streams`
`Streams`はDartのコアライブラリの一部として実装されていますが、Swiftでは実装されていません。

Dartのドキュメントを引用します。

>`Stream`は非同期イベントのシーケンスです。

`Stream`はリアクティブなアプリケーションの基本であり、状態管理で重要な役割を果たします。

例えば、ユーザーが検索フィールドのテキストを更新するたびに、新しい結果のセットが出力されます。

`Stream`はSwiftのコアライブラリには含まれていません。`RxSwift`のようなサードパーティのライブラリは`Stream`に対するサポートやその他多くの機能を提供しています。

ストリーム(`Stream`)は幅広いトピックなので、ここでは詳しく説明しません。


##メモリ管理
Dartは高度なガベージコレクション(**garbage collection**)方式でメモリを管理します。

Swiftは自動参照カウント(**ARC**)でメモリを管理します。

これは、メモリが使われなくなるとすぐに解放されるので、優れたパフォーマンスを保証します。

しかし、コンパイラから開発者に負担を部分的にシフトしています。

Swiftでは、保持サイクルを回避するためにオブジェクトのライフサイクルと所有権について考慮し、適切なキーワード（`weak`,`strong`,`unowned`）を正しく使う必要があります。


##コンパイルと実行

まず最初に、ジャストインタイム`just-in-time`(JIT)コンパイラと事前`ahead-of-time`(AOT)コンパイラの重要な違いを説明します。

###JITコンパイラ
JIT コンパイラはプログラムの実行中に実行され、その場でコンパイルを行います。

JIT コンパイラは、型が事前に固定されていない動的な言語で使用されるのが一般的です。JITプログラムはインタプリタや仮想マシン(VM)を介して実行されます。

###AOTコンパイラ
AOT コンパイラはプログラムの作成時に実行前に実行されます。

AOT コンパイラは通常、データの型を知っている静的言語で使用されます。AOTプログラムはネイティブのマシンコードにコンパイルされ、実行時にハードウェアによって直接実行されます。

`Wm Leler`氏のこの素晴らしい記事を引用します。

>AOTコンパイルが開発中に行われる場合、開発サイクル（プログラムに変更を加えてからその変更の結果を見るためにプログラムを実行できるようになるまでの時間）が大幅に遅くなります。しかし、AOT コンパイルは、実行時に解析やコンパイルのために一時停止することなく、より予測可能なプログラムを実行することができます。また、AOTコンパイルされたプログラムは、（すでにコンパイルされているため）より速く実行を開始します。  
逆に、JITコンパイルは開発サイクルを大幅に短縮しますが、実行が遅くなったり、不安定になったりします。特に、JIT コンパイラはプログラムの実行を開始すると、コードを実行する前に解析とコンパイルを行わなければならないため、起動時間が遅くなります。研究によると、実行開始までに数秒以上かかると、多くの人がアプリを放棄してしまうという結果が出ています。

静的言語として、Swiftは事前にコンパイルされます

Dartは**AOT**と**JIT**の両方でコンパイルできます。これはFlutterと併用した場合に大きなメリットがあります。

再度引用します。

>開発時には、特に高速なコンパイラを使ってJITコンパイルを行います。そして、アプリのリリース準備が整ったら、AOTコンパイルを行います。その結果、先進的なツールとコンパイラの力を借りて、Dartは、開発サイクルの超高速化と、実行時間及び起動時間の高速化という両世界のベストを実現することができます。-` Wm Leler`

Dartを使うと、両世界の最高のものを手に入れることができます。

SwiftはAOTコンパイルに主な欠点があります。つまり、コンパイル時間はコードベースのサイズに応じて増加します。

中規模のアプリ（10Kから100K行）では、アプリのコンパイルに数分かかることがあります。

Flutter アプリの場合はそうではなく、コードベースのサイズに関係なく、常に一秒以内のホットリロード(`hot-reload`)ができます。


##その他の機能
以下の機能は、DartとSwiftはかなり似ているので取り上げませんでした。

- 演算子
- 文字列
- Swiftではオプショナルチェイニング`Optional chaining`（Dartでは条件付きメンバーアクセスとして知られています）

###並行性
- 同時で並行プログラミングはDartの`isolate`で提供されています。
- Swiftは`Grand Central Dispatch (GCD)`とディスパッチキュー(`dispatch queue`)を使用します。

##Dartに欠けている私のお気に入りのSwiftの機能

- 構造体
- 関連する型を持つ列挙型
- オプションナル


##Swiftに欠けている私のお気に入りのDartの機能

- JITコンパイラ
- Future と `await/async` 
- Stream と `yield/async*`（RxSwiftはリアクティブアプリケーション用のストリーム(`Stream`)のスーパーセットを提供しています)


##結論

DartとSwiftはどちらも優れた言語であり、現代のモバイルアプリやそれ以上のものを構築するのに適しています。

どちらの言語も独自の長所を持っているので、どちらが優れているということはありません。

モバイルアプリの開発と2つの言語のツールを見ると、私はDartが優位に立っていると感じます。これは、Flutter のステートフルホットリロード`stateful hot-reload`の基盤となっている JIT コンパイラによるものです。

ホットリロードはアプリを構築する際に生産性を大きく向上させます。

開発者の時間は、コンピューティングの時間よりも希少なリソースです。

そのため、開発者の時間を最適化することは非常にスマートな動きです。

一方で、Swiftは非常に強力な型システムを持っていると感じています。型の安全性はすべての言語機能に組み込まれており、より自然にロバスト(**頑健**)なプログラムにつながります。

個人的な好みはさておき、プログラミング言語は単なるツールに過ぎません。そして、その仕事に最も適したツールを選ぶのが開発者としての私たちの仕事です。

いずれにしても、どちらの言語もお互いに最高のアイデアを借りながら進化していくことを期待しています。