【Flutter】React Native エンジニアが学ぶ Dart
普段は業務で React Native を使用したアプリケーションを作成しているので、そこと対比しつつ学んでいます。
今回はまず Dart 言語 から学習したのでその記録となります。
Dart
Dart is a client-optimized language for developing fast apps on any platform. Its goal is to offer the most productive programming language for multi-platform development, paired with a flexible execution runtime platform for app frameworks.
Dartは、あらゆるプラットフォームで高速なアプリケーションを開発するために、クライアントに最適化された言語です。その目標は、マルチプラットフォーム開発のための最も生産性の高いプログラミング言語と、アプリケーションフレームワークのための柔軟な実行ランタイムプラットフォームの組み合わせを提供することです。
つまり Web, ネイティブアプリ両方の開発体験をよくするための言語。WebだとJavaScriptほぼ一択になってしまうフロントエンドの代替となる期待があります。
変数
Dartは静的型。変数は型推論が効くかつ、自分で型定義を記述することも可能です。
void main() {
int age = 12;
double height = 170.5;
String name = "John"; // '' でも可
bool isAdult = false;
}
var
は最初の代入時に型推論されます。
void main() {
var weight = 61.2; // double型
weight = "70.3"; // Type Error
}
// Error: A value of type 'String' can't be assigned to a variable of type 'double'.
型宣言キーワードは他にもあります。
void main() {
dynamic aaa = 123; // TSでいう any あらゆる型が代入可
final bbb = "bbb"; // JSでいう const 再代入不可
const ccc = "ccc"; // 同じく再代入不可( コンパイル時に確定)
}
条件分岐 / ループ
if
/ switch
/ for
はほとんど JavaScript と同様。
void main() {
const age = 18;
if (age >= 18) {
print("Adult");
} else {
print("Child");
}
}
列挙型
主な列挙型として、List
/ Set
/ Map
があります。
List
配列型。
void main() {
List<int> cards = [1, 3, 12, 13];
print(cards[cards.length -1]); // cards[-1] は不可
}
Set
重複不可。
void main() {
Set<String> names = {"一郎", "二郎"};
names.add("一郎");
print(names); // {"一郎", "二郎"}
}
Map
key-value の 辞書型。JSでいうオブジェクト。
void main() {
var book1 = {"title": "The Humble Programmer",
"auther": "Edsger W. Dijkstra",
"price": 1200}
print(book1["title"]);
}
関数
最初に返り値から書き、引数にも型をつけます。
int add(int a, int b) {
return a + b;
}
アロー関数的な書き方も可能です。
int add(int a, int b) => a + b;
[]
で囲まれた引数は省略可能です。 (省略された場合はnullになります)
{}
で囲むことで名前つき引数にできます。(省略された場合はnullになります)
int add1(int a, int b, [int c, int d]) => a + b;
int add2(int a, int b, {int c, int, d}) => a + b;
add2(1, 2, c: 3);
クラス
ほとんどJavaScriptと同じです。
セッターの書き方は、押さえておきたいポイントです。
class Monstar {
// インスタンス変数
String name;
int defence;
int hp;
// コンストラクタ
Monstar(this.name, this.defence, this.hp);
// セッター(this.hp に新たな値を代入する)
set protect(int damage) => hp = hp - (damage - defence);
// ゲッター
String get status => "Name: $name, HP: $hp";
}
void main() {
var monstar1 = Monstar("Wild Wolf", 10, 120);
monstar1.protect = 30;
print(monstar1.status); // Name: Wild Wolf, HP: 100
}
継承
クラスは extends
キーワードで 継承 することができ、super
で親クラスの変数やメソッドアクセスが可能です。
コンストラクタは継承できないので、再度定義してやる必要があるそうです。
class Monstar {
// インスタンス変数
String name;
int defence;
int hp;
// コンストラクタ
Monstar(this.name, this.defence, this.hp);
}
class Boss extends Monstar {
// コンストラクタ
Boss(String name, int defence, int hp): super(name, defence, hp);
}
オーバーライド
@override
キーワードを使用し、親クラスのメソッドを上書きできます。
class Television {
// ···
set contrast(int value) {...}
}
class SmartTelevision extends Television {
set contrast(num value) {...}
// ···
}
ミックスイン
Rustの impl
のようなメソッド拡張です。
mixin Jump {
void jump() {
print("Pyon!");
}
}
mixin Sleep {
void sleep() {
print("zzz...");
}
}
class Monstar with Jump, Sleep {
...
}
インターフェース
TypeScritpの interface
や Swiftのプロトコルっぽい使い方で、クラスを拡張できます。
先程の mixin
を class
に戻し、with
の代わりに implements
キーワードを使用することで、継承元クラスと同様のインターフェース実装を強要することができます。
class Jump {
void jump() {
print("Pyon!");
}
}
class Sleep {
void sleep() {
print("zzz...");
}
}
class Monstar implements Jump, Sleep {
...
void jump() {...}
void sleep() {...}
}
抽象クラス
abstruct
キーワードで定義される抽象クラスは、継承のみに使用でき、そのままではインスタンス化できません。
abstruct Monstar {
...
}
ジェネリクス
TypeScriptや、他言語と同じですので省略します。
try - catch
catch
句 で エラーオブジェクトに加え、スタックトレースにアクセスすることが可能です。
void main() {
try {
throw "Error!"
} catch(e, s) {
...
} finally {
...
}
}
enum
パターンマッチに使用できます。
enum Animal = { dog, cat, mouse }
var animal = Animal.cat;
非同期処理
async
/ await
のコンセプトは同様で、Future
キーワードを使用します。 Future
は JSの Promise
に相当します。 (ちなみに、JSの Promise
は元々 Future
という名前でした)
// 非同期関数は Futureを返す
Future<void> fetchUser() {
return Future.delayed(
const Duration(seconds: 2),
() => print('User Info Fetched!')
);
}
void logUserName() async{
print("Fetching user info...");
await fetchUser();
}
Fetching user info...
# ...2秒後
User Info Fetched!
ガイド
Dart公式から、ベストプラクティスのガイドが公開されています。
参考
Discussion