Introduction to Dart を見ておく (1)

# はじめに

https://qiita.com/grhg/items/365c7a1f9c84dbeeb0ca

Flutter に入門してみて、Dart は他のプログラミング言語をやったことがあれば、読むのは苦労しなそうでした。

とはいえ、以下の Introduction to Dart で基本はさらっておこうと思います。

https://dart.dev/language

少し長いため2回に分けます。

# 想定読者

プログラミング言語自体はいくつか触ったことがあるが、Dartは初めての人。

# Dart とは？

Google によって開発されたプログラミング言語です。
ウェブアプリやモバイルアプリのクライアント開発向けに設計され、サーバーやデスクトップ向けアプリケーションの開発にも使用できます。
Flutter で利用されていることで注目されていますね。

Dart の特徴として、公式サイトでは以下を挙げています。

- 親しみやすさ
一貫性があり、簡潔で、型が強いプログラミング言語。
モダンな機能として、Null Safety（ヌル安全）やパターンマッチングをサポートしているので、直感的かつ安全に開発を進められる。
- 生産性の高い開発
ホットリロード機能を活用して、アプリを実行中でもコードを変更して即座に結果を確認できる。
これにより、反復的な開発サイクルが高速化される。
- 全てのプラットフォームでの高速性と移植性
モバイル、デスクトップ、バックエンド向けには、ARM、x64、RISC-Vのネイティブコードにコンパイル可能。
また、Web向けにはJavaScriptやWebAssemblyにコンパイルすることで、幅広いプラットフォームに対応。

# Introduction to Dart

では、早速みていきたいと思います。
[DartPad](https://dartpad.dev) を使えば、Web上で実行することができます。

## Hello World

基本の Hello World からです。
実行の開始として、お馴染みの `void main()` を使います。

```dart
void main() {
  print('Hello, World!');
}
```

実行結果
```
Hello, World!
```

## Variables

### 基本的に方は省略可能

Dart は型安全ですが、`var`を使って型推論ができます。

```dart
var name = 'Voyager I';
var year = 1977;
var antennaDiameter = 3.7;
var flybyObjects = ['Jupiter', 'Saturn', 'Uranus', 'Neptune'];
var image = {
  'tags': ['saturn'],
  'url': '//path/to/saturn.jpg'
};
```

型を指定する場合

```dart
String name = 'Voyager I';
int year = 1977;
double antennaDiameter = 3.7;
List<String> flybyObjects = ['Jupiter', 'Saturn', 'Uranus', 'Neptune'];
Map<String,Object> image = {
  'tags': ['saturn'],
  'url': '//path/to/saturn.jpg'
};
```

型も馴染みのあるものが多いですね。

### Nullable (ヌル許容)

`?`をつけることで、Nullableを指定できます。

```dart
void main() {
  String name;
  String? address;
  print(name);
  print(address);
}
```

非Nullable の値を設定前に使うと以下のようにコンパイル時にエラーとなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3294382/5a7b16d0-ccb6-84d6-4260-aef1c9d70ff3.png)

null を設定しようとしても同様です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3294382/141c1c38-3c33-9143-74f4-6f7629fbbf11.png)

### 初期化の遅延

`late` を付けると初期化を遅延できます。
通常、使用前までに初期化していれば、エラーにならないが、トップレベルで宣言した場合など、使用前に初期化していてもコンパイルエラーになってしまうケースがあります。
その場合は、`late` を付けることでエラーを抑止できます。

```dart
late String description;

void main() {
  description = 'Feijoada!';
  print(description);
}
```

ただし、`late` を付けて初期化を忘れて利用してしまうと、実行時エラーになってしまいます。

```
DartPad caught unhandled LateError:
LateInitializationError: Field 'description' has not been initialized.
```

## final と const

final => 1度だけセットできる
const => コンパイル時に評価される
両方とも、`var` の代わりに利用するか、型の前につけて使うことができます。

```dart
void main() {
  final finalVal;
  // const は初期化時に設定
  const String constVal = "def";
  
  // final は後から設定できる
  finalVal = "abc";
  // 2回設定しようとするとコンパイルエラー
  //finalVal = "abc2";
  
  print(finalVal);
  print(constVal);
}
```

## Control flow statements

`if` での条件分岐、`for` や `while` でのループは Dart でも使えます。
使い方も変わったところはなさそうです。

```dart
if (year >= 2001) {
  print('21st century');
} else if (year >= 1901) {
  print('20th century');
}

for (final object in flybyObjects) {
  print(object);
}

for (int month = 1; month <= 12; month++) {
  print(month);
}

while (year < 2016) {
  year += 1;
}
```

## Functions

`Functon` も特に難しい部分はなさそうですね。
戻り値の型を省略できますが、指定するのが推奨だそうです。

```dart
int fibonacci(int n) {
  if (n == 0 || n == 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
}

void main() {
  print(fibonacci(20));
}
```

1行しか無い場合は、`=>` を使った省略形で `Function` を定義できます。
```dart
flybyObjects.where((name) => name.contains('turn')).forEach(print);
```

## コメント

`//` `///` `/* */` の３種類のコメントがあります。

```dart
// 通常の一行コメント

/// ドキュメンテーション用のコメント
/// IDEやDartdocでドキュメントコメントとして扱われる

/* 開始と終端を指定するタイプのコメント */
```

## Import

別ライブラリで定義されたAPIは `import` 文でインポートします。

```dart
// Importing core libraries
import 'dart:math';

// Importing libraries from external packages
import 'package:test/test.dart';

// Importing files
import 'path/to/my_other_file.dart';
```

## Class



```dart
class Spacecraft {
  String name;
  DateTime? launchDate;

  // Read-only non-final property
  int? get launchYear => launchDate?.year;

  // コンストクタ：this.name のように指定することで、メンバ変数に設定することができる
  Spacecraft(this.name, this.launchDate) {
    // ...
  }

  // unlaunched という名前をつけたコンストラクタ。内部でデフォルトコンストラクタを呼び出している
  Spacecraft.unlaunched(String name) : this(name, null);

  // メソッド
  void describe() {
    print('Spacecraft: $name');
    // Type promotion doesn't work on getters.
    var launchDate = this.launchDate;
    if (launchDate != null) {
      int years = DateTime.now().difference(launchDate).inDays ~/ 365;
      print('Launched: $launchYear ($years years ago)');
    } else {
      print('Unlaunched');
    }
  }
}

void main() {
  var voyager = Spacecraft('Voyager I', DateTime(1977, 9, 5));
  voyager.describe();

  var voyager3 = Spacecraft.unlaunched('Voyager III');
  voyager3.describe();
}
```

実行結果

```
Spacecraft: Voyager I
Launched: 1977 (47 years ago)
Spacecraft: Voyager III
Unlaunched
```


# 終わり

Dart の基本文法を見てきました。
JavaScript 等 他の言語と似ている部分が多く、とっつきやすいですね。
では、続きは次回にしたいと思います。