Dart 1.19がリリースされました。今回のStrong Mode周りの変更などはなかなか便利なので紹介していきます。
関連リンク
- 開発ブログ : Dart News & Updates: Dart 1.19: Improved developer experiences
- CHANGELOG : sdk/CHANGELOG.md at master · dart-lang/sdk
1.19 変更点
言語仕様の変更
最後の引数やパラーメータにカンマをつけることが可能に
関数宣言における最後のパラメーターや関数呼び出しにおける最後の引数のあとにtrailing commaをつけることが可能になりました。開発が楽になりますね。
void main() {
var test = new TestClass(
str1:"A",
str2:"B",
str3:"C",
str4:"D", // この行の最後のカンマがつけられるようになった
);
test.func2(); // ABCD
}
class TestClass {
String str1,str2,str3,str4;
TestClass({
this.str1,
this.str2,
this.str3,
this.str4, // この行もOK!
});
void func2(){
print(str1 + str2 + str3 + str4);
}
}
これは開発ブログに表示されていたgifを見るとさらにわかりやすいと思います。
画像元: Dart News & Updates: Dart 1.19: Improved developer experiences
関連Issue : Allow trailing commas in parameter and argument lists. · Issue #26644 · dart-lang/sdk
周辺ツールの変更点
dartfmt
上の言語仕様の変更にともなってtralling commas関連のフォーマットをサポートしました。そのほかにも改善されたようです。詳しくはdart_styleレポジトリのCHANGELOGを確認してください。
Pub
主要な変更を取り上げていきます。その他はCHANGELOGを確認してください。
-
--no-packages-dir
フラグがpub get
、pub upgrade
、pub downgrade
に追加されました。このフラグをつけてコマンドを実行すると、pubはpackages/
をせず、またもしある場合も削除してくれます。これは--no-package-symlinks
フラグがサポートされなくなったものを埋め合わせるためのものです。 -
Flutter SDKのバージョンをpubspec.yamlの中で指定できるようになりました。
pubspec.yaml
environment:
flutter: ^0.1.2
sdk: >=1.19.0 <2.0.0
- packageの`dependencies`を指定する際に、sdkからそのpackageを取得するためのオプション`sdk`が追加されました。現在はflutterだけサポートされています。上の変更と合わせてflutter関連のためのようですね。
```yaml:pubspec.yaml
dependencies:
flutter_driver:
sdk: flutter
version: ^0.0.1
関連Issue
dart2js
-
dart2dart
( =dart --output-type=dart
)が削除されました。1.11からdeprecated だったのでそこまで影響はないと考えられます。
DartVMについて
DartVMをビルドするために、C++11をサポートするコンパイラが必要になりました。古いバージョンのLinuxディストリビューションを利用している場合は注意が必要です。GCC4.8以上が必要とのことです。clangやXCodeで使われているコンパイラでは問題なく動くことが確認されています。
参考 : Building · dart-lang/sdk Wiki
Strong Mode
AnalyzerのStrong Modeがさらに強力になりました。追加された機能を見てみましょう。
新機能
Disable implicit casts
これは名前のとおり暗黙のダウンキャストを許可しないオプションです。ダウンキャストとは、基底クラスから派生クラスへの型変換を指します。下のサンプルコードを確認してみてください1。
void main(){
Base test = new Base();
Sub test2 = test; // disable implicit castsを有効にするとここでerrorに
print(test2.str2); // こういうエラーを事前に検知できる
}
class Base {
String str;
}
class Sub extends Base {
String str2;
}
使いたい場合は.analysis_optionsで指定するか、
analyzer:
strong-mode:
implicit-casts: false
もしくはdartanalyzerで--no-implicit-casts を指定してください。
dartanalyzer --strong --no-implicit-casts ~.dart
Disable implicit dynamic
これは暗黙のdynamicを禁止するものです。ドキュメントにのっているサンプルコードがわかりやすいです。
main() {
var x; // これはエラー
var i = 123; // これはintと推論できるのでOK
dynamic y; // これはdynamicで宣言しているのでOK!
}
ドキュメントに
This also affects: parameters, return types, fields, creating objects with generic type, generic functions/methods, and supertypes
とあるように、これは多くの場所で作用します。
// これもエラーになります。
f(x) => x + 42;
dynamic f(dynamic x) => x + 42; //OK!
int f(int x) => x + 42; // okay
// クラス内のメンバー変数にも作用
class C {
var f; // これはエラー
dynamic f; // OK!
}
main() {
var x = []; // 暗黙で List<dynamic> になっているのでだめ
var y = [42]; // OK!: List<int>
var z = <dynamic>[]; // OK!: List<dynamic>
T genericFn<T>() => null;
genericFn(); // 暗黙で genericFn<dynamic> になっているのでだめ
genericFn<dynamic>(); // OK
int x = genericFn(); // OK: 暗黙の genericFn<int>だということがわかる
}
// エラー
class C extends Iterable { /* ... */ }
// OK
class C extends Iterable<dynamic> { /* ... */ }
使いたい場合は.analysis_optionsで指定するか、
analyzer:
strong-mode:
implicit-casts: false
もしくはdartanalyzerで--no-implicit-dynamic
を指定してください。
dartanalyzer --strong --no-implicit-dynamic *.dart
上2つの機能はどちらも開発中のものです。フィードバック募集中とのことでもありますし、便利ですので使ってみてはいかがでしょうか。
Breaking Chanages
-
コンストラクタを呼び出すときの変数から推論をしてくれるようになりました。
var map = new Map();
// infer: Map
var otherMap = new Map.from(map);
関連Issue : [infer constructor type arguments from values · Issue #25220 · dart-lang/sdk](https://github.com/dart-lang/sdk/issues/25220)
- ローカル関数の返り値を推論してくれるようになりました。
```dart
void main() {
// 返り値はintだと推論してくれる
f() { return 40; }
int y = f() + 2; // 型チェック
print(y);
}
関連Issue : infer local function return types · Issue #26414 · dart-lang/sdk
- ジェネリック型のパラーメーターにおけるtype promotionを許可するようになりました。
void fn/*<T>*/(/*=T*/ object) {
if (object is String) {
// `object`はこのblockの中では`String`として扱われる
print(object.substring(1));
}
}
関連Issue : "is" checks aren't considered with generic-method types · Issue #26965 · dart-lang/sdk
-
Future.then
に関する推論が賢くなりました。.then/*<Future<SomeType>>*/
が必要なくなりそうです。
// これも推論してくれる
Future<List<int>> t2 = f.then((_) => [3]);
// これもOK.
Future<int> t2 = f.then((_) => new Future.value(42));
関連Issue: Can strong mode inference for Future.then be improved? · Issue #25944 · dart-lang/sdk
- async 関数に関する推論も賢くなりました。
void test() async {
List<int> x = await [4]; // これは今までも推論してくれていた
List<int> y = await new Future.value([4]); // 今はこっちも推論してくれる
}
関連Issue : Handle implicit future unions in downwards inference · Issue #25322 · dart-lang/sdk
- Sideway castsが禁止されました。
関連Issue : Sideways casts should be disallowed · Issue #26120 · dart-lang/sdk
もろもろの変更を見ても、かなり快適にStrong Modeの恩恵をうけることができるようになっている印象を受けます。よい。
あとがき
一時期消えたなどと言われていたDartですが、ここのところはFlutterやAngular2、Googleの新OS「Fuchsia」への採用などのニュースで活気づいています。Dart 2.0のリリースなどもふくめて、Dart Summit 2016までいろいろな動きがありそうです。興味深いものがあったらまとめて行きたいと思います。