K.Shirakiをフォローする

10分で書けるようになる Dart 講座

dartロゴ
フロントエンドバックエンド

Flutter を広めたい

最近社内で Flutter の機運が高まっているので、以前から Flutter を触っている私としてはこの機会にもっと Flutter の良さを広めていきたいです
そこで今回は Flutter で使われているプログラミング言語である Dart を10分で爆速解説していきたいと思います
これを読めば10分後にはすぐにコーディングできます(たぶん)

Flutter とは

Google によって開発された2018年生まれの比較的新しいフレームワークです
1つのソースコードから

  • Web
  • Android
  • iOS
  • Windows

など複数の環境のアプリがつくれるすごいやつです
「とりあえずなんかアプリを作ってみたい!」という方にはぜひおすすめです

公式サイト:https://flutter.dev/

Dart の概要

JavaScript の代替となる言語を目指して Google によって開発されました
似たようなコンセプトのライバルとして TypeScript がありますね
2011年生まれで当初はマイナーな言語でしたが Flutter の開発言語に採用されたことで注目が高まっています

触った感触をざっくり言うと Java と JavaScript を融合させたような感じです
学習コストは比較的低く、JavaScript を触ったことがある人ならほぼ予備知識なしですぐにコーディングを始められると思います

この記事では主に Java, JavaScript と微妙に違う部分をかいつまんで解説していきます

Dart の特徴

Hello world はこんな感じ

// コメントはこのように書きます

/* このようにも書けます */

/// スラッシュが3つだと doc コメントになります

// main は特別な関数で、Dart アプリケーションは常にこの関数から始まります
void main() {
  print("Hello, World!");
}

特徴1:強い静的型付け

Dart では変数を宣言する場合、Java のように型名 変数名の形で宣言します

String greeting = "こんにちは!";

// 整数の型は int です(Number ×, Integer ×)
int age = 20;

また、var で宣言をすれば型が自動的に判別されます(let はありません)

// 初期値が String なので String型として解釈される
var greeting = "こんにちは!";

定数を宣言したいときは const、再代入をさせたくない場合は、final をつけて宣言します

const String greeting = "こんにちは!";
final String name = "太郎";

// late を付ければ初期値の代入を後からすることもできます
late final int age;

const で宣言した変数はコンパイル時に決まっている必要があります
従って、JavaScript での const は Dart での final に近いです(少しややこしい)

また、引数の型が予め決まらない場合などは dynamic という型も使えます
(TypeScript で言うところの any

特徴2:Null かどうかめっちゃ気にする

Dart では宣言時に null が代入されうるかどうかを宣言時に決めてしまいます
null が入るかもしれない変数は宣言時の型名の後ろに ? をつけて宣言します
null が許容されている場合の初期値は null になるので、JavaScript で言うところの undefined はありません)

String? middleName = null;

逆に言えば ? を付けずに宣言された変数には絶対に null が入らないので、いちいち null チェックをする必要がありません

String firstName= "太郎";

if(firstName != null) { // 不要
    print(firstName);
}

また、JavaScript で言うところの Null 合体演算子やオプショナルチェーンも使えます

String? middleName = null;

print(middleName ?? "ミドルネームはありません"); // null だった場合の値を設定できる
print("文字数は${middleName?.length}") // null 参照エラーにならない
middleName ??= "アレクサンダー" // null なら代入する

特徴3:関数の宣言に function はいらない

Dart での関数は 戻り値の型名 関数名(引数の型名 引数名){} の形で宣言します

bool isEven(int num) {
  return num % 2 == 0;
}

// 戻り値がない場合は void を指定します
void sayHello() {
  print("Hello!");
}

アロー関数式も使えますが、JavaScript とは少し勝手が違います
Dart でのアロー関数式は単に {return 戻り値;} を省略したものです
{} の中に処理を複数行に渡って書くことはできません

// JavaScript ではよく見る形ですが Dart では使えません
var add = (x, y) => {
    return a + b;
}

// Dart では多くの場合、単にこう書きます
int add(int x, int y) {
    return x + y;
}

// この式は上と全く同じ意味です
int add(int x, int y) => x + y;

特徴4:名前付き引数が使える

引数を {} で囲むと名前付き引数になります
引数名: 引数 の形で渡します

void greet({String name, String text}) {
  print("$nameさん! $text");
}

greet(name: "太郎", text: "こんにちは!"); // 太郎さん! こんにちは!

特徴5:クラスに関するあれこれは大体 Java といっしょ

クラスに関する構文は大体 Java といっしょですが、ところどころ略記法が使えます

class Person {
  // Java のようなアクセス修飾子はありません(デフォルトですべて public)
  // 変数を隠蔽したい場合は、変数名の頭にアンダースコア(_)をつけます
  int _height;

  // コンストラクター
  // よくあるプロパティの代入はこれだけで OK です
  Person(this._height);
  
  // ゲッター、セッターも以下のように略記できます
  int get height => _height;
  set height(int height) {
    _height = height;
  }
}

void main() {
  // new は省略できます
  Person person = Person(170);

  // ゲッター、セッターを実装すれば、プロパティにアクセスするかの如く扱えます
  person.height = 171; // 身長伸びた!
  print("身長は${person.height}");
}

(注意)Dart ではあまり Java のようにゲッター、セッターを多用しないようです
https://dart.dev/tools/linter-rules/unnecessary_getters_setters

特徴6:mixin でコードを再利用できる

Dart は単一継承ですが、mixin という形でコードの再利用ができます
PHP でいうところの Trait のようなものです

// abstract で抽象クラス
abstract class Animal {
  void sleep() {
    print("すやすや");
  }
}

// extends で継承
class Dog extends Animal {
  void bark() {
    print("わんわん");
  }
}

// mixin を定義
mixin Wing {
  void fly() {
    print("ばさばさ");
  }
}

// with で mixin を使う
class Bat extends Animal with Wing {
  void hang() {
    print("ぶらぶら");
  }
}

void main() {
  Dog dog = Dog();
  dog.sleep(); // すやすや
  dog.bark(); // わんわん
  
  Bat bat = Bat();
  bat.sleep(); // すやすや
  bat.fly(); // ばさばさ
  bat.hang(); // ぶらぶら
}

特徴7:配列は List、連想配列は Map

Java と大体いっしょです

// 配列(要素の型は String)
List<String> names = ["太郎", "次郎", "三郎"];

// 連想配列(JavaScript で言うところのオブジェクト)
Map<String, int> ages = {
  "太郎": 30,
  "次郎": 25,
  "三郎": 20,
};

特徴8:Enum も使えます

TypeScript だとあまり使われない enum ですが Dart ではバリバリ使えます

enum Colors {
  green, 
  yellow, 
  red
}

void signal(Colors color) {
  switch(color) {
    case Colors.green:
      print("Go!");
    case Colors.yellow:
      print("Be careful...");
    case Colors.red:
      print("Stop!");
  }
}

(注意)Dart 3 から switch 文の case がフォールスルーされなくなったので処理を case ごとに終わらせる場合 break; は不要になりました
また、文ではなく式として使えるようにもなっており、より強力になっているようです
https://dart.dev/language/branches#switch

特徴9:Promise じゃなくて Future

// 処理が完了したら String になる Future を返す
Future<String> fetch() async {
  return await api();
}

// JavaScript ではこのように書きますが、async の位置が違うので注意
async function fetch() {
  return await api();
}

約束じゃなくて未来なんですね

10分経ったので Let’s try!

公式でオンラインエディタが用意されているので、今すぐ試せます!
https://dart.dev/#try-dart

まとめ

今回は Dart の基礎に絞って紹介しました
次回は Flutter の基礎について紹介できたらいいなと思います

参考

Dart programming language
Dart is an approachable, portable, and productive language for high-quality apps on any platform.