Kotlinの as?
便利ですよね。
hogeがHoge型の値ならresultはHogeとして認識され、たとえばStringなど別の型だった場合はnullとして扱われます。
class Hoge
val result: Hoge? = hoge as? Hoge
Dartにも as
はあるのですが、Kotlinのように as?
と書くことはできずに、単純なキャストとしての役割になっています。
class Hoge {}
final hoge = "hoge";
hoge as Hoge?; // TypeError
早速ですが、Dartだとどのように書くのかを解説していきます。
- チェック用クラス
abstract class Hoge {}
class Foo extends Hoge {
final name = 'foo';
void foo() {
print('result: foo');
}
}
class Bar extends Hoge {
final name = 'bar';
final baz = 100;
void bar() {
print('result: bar');
}
}
1番簡単なのはif文内でcase式を使うやり方です。
これはDart3.0で導入されました。
この書き方ならば、hogeがnullの時にif文はfalseになるのでKotlinのas?
と同様の効果が得られます。
これだとif文の中でしかsmart castされませんが、早期returnにすれば以降の文でもsmart castされます。
final Hoge? hoge = Foo();
if(hoge case final Foo foo) {
foo.foo();
}
// result: foo
if文だけでなく、switch文でも書けます。
as?のように型マッチを調べるだけの用途からは脱線しましたが、複数パターンの型を1度に調べられるので、実際のプロダクト開発では頻出するパターンかなと思います。
final Hoge? hoge = Foo();
switch (hoge) {
case final Foo foo:
foo.foo();
case final Bar bar:
bar.bar();
default:
print('undefined');
}
// result: foo
Dart3.0からswitchは式でも表せるようになったので、そのまま値を代入することもできます。
final Hoge? hoge = Bar();
final result = switch (hoge) {
final Foo foo => foo.name,
final Bar bar => '${bar.name}, ${bar.baz}',
_ => 'undefined'
};
print(result); // bar, 100
今までのDartっぽくない書き方もできて、このようにswitch内で新たに変数名を定義してあげることもできます。
final Hoge? hoge = Bar();
final result = switch (hoge) {
Foo(name: final n) => n,
Bar(name: final n, baz: final b) => '$n, $b',
_ => 'undefined'
};
print(result); // bar, 100
本題とは逸れますが、switch同様にifでもこのように書き換え可能です。 プロパティも全て書く必要がないので、条件式内で利用するものだけ書くと結構便利です。
if (hoge case Bar(baz: final b)) {
print(b);
}
まとめ
Dart3.0になってからは as?
相当の書き方も便利になり、かなり書き方の自由度が増えた感じがします。
もはやas?を足して欲しい気もしますが、現状でも充分使えると思います。
Dart3.0で便利になったSwitchの使い方はこちら にまとめているので興味がある方はご覧ください。