「 Flutter のコードの中で出てくる extends ってなんだろう? 」
本記事ではそんな疑問にお答えします。
Flutter / Dart での extends
の役割について解説します。
コードリーディングの役に立つ知識となっています。
丁寧に解説しますので、ぜひ読んでみてください!
extends って何?
extends の役割
extends
はクラスの拡張を表すキーワードです。
あるクラスに対し、そのクラスの機能を持ちつつ、追加の機能を持つサブクラスを
作成するのに用います。
具体例
拡張クラスの作成方法から、その特徴まで具体例を用いて解説します。
拡張クラスの作成
Monkey
というクラスを作成してみます。
class Monkey{
const Monkey({required this.name});
final String name;
void move(){
print('move!');
}
void cry(){
print('screech!');
}
}
name
というフィールドを持ち、move
というメソッドと、cry
というメソッドを持つクラスです。
このクラスを拡張したクラスとして、Human
というクラスを以下のように作成します。
class Human extends Monkey{
const Human({required super.name});
void sayTheName(){
print(name);
}
}
extends
の後にMonkey
と続けることで、Monkey
クラスを拡張したクラスとして定義できます。
ここで、Monkey
クラスでname
というフィールドは必須です。
拡張したクラスのHuman
クラスでは
元のMonkey
クラス のname
フィールドに値を設定する必要があります。
設定するための一つの方法がコンストラクタの引数として同様に受け取る方法です。
拡張していない場合はrequired this.name
と書くところを、required super.name
と書くことで、
元のMonkey
クラス のname
フィールドに値を設定することができます。
Human
クラスのsayTheName
メソッドは、name
というフィールドを参照しています。Human
クラスでname
フィールドは定義していないため、一見エラーになりそうですが、
拡張元のMonkey
クラスで定義されているため、エラーとならなりません。
以上が、拡張クラスの作り方と解説になります。
メソッドの実行
上で定義したHuman
クラスを使って、以下のコードを実行してみましょう。
void main(){
print('Human'); // 実行結果: Human
final human = Human(name: 'Aoi');
human.move(); // 実行結果: move!
}
上のHuman
クラスのコードの中にはmove
というメソッドは定義されていません。
ですが、human.move();
でエラーは発生せず、move! という実行結果が返ってきます。
これは拡張することにより、Human
クラスがMonkey
クラスの機能を持つ
(Monkey
クラスで定義したmove
というメソッドを使える)
ためです。
メソッドの上書き
Human
クラスを以下のように修正し、メソッドを追加しましょう。
class Human extends Monkey{
const Human({required super.name});
@override
void cry(){
print('uwaaaaaaah');
}
void sayTheName(){
print(name);
}
}
Monkey
で定義していたcry
メソッドをもう一度定義し直しています。
クラスの拡張では、元のクラス(Monkey
)のメソッドをサブクラス(Human
クラス)にて、
上書きすることができます。
これをオーバーライドする、といいます。
以下のように、Monkey
クラスのcry
メソッドと、Human
クラスのcry
メソッドの実行結果を比較してみましょう。
void main(){
print('Monkey'); // 実行結果: Monkey
final monkey = Monkey(name:'George');
monkey.cry(); // 実行結果: screech!
print('Human'); // 実行結果: Human
final human = Human(name: 'Aoi');
human.cry(); // 実行結果: uwaaaaaaah
}
上書きが上手くいっていることが確認できます。
以上が上書き(オーバーライド)の解説でした。
以下のDartPadで今回紹介したサンプルを実際に実行してみて学ぶことができます。
是非参考にしてみてください。
Flutterでの例
flutter create
で作られるカウンターアプリで、このようなクラスがあります。
class MyApp extends StatelessWidget {
const MyApp({super.key});
// コメント省略
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// コメント省略
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
StatelessWidget
クラスをextends
しているので、
このMyApp
というクラスは、StatelessWidget
を拡張したクラス、となります。
これにより、MyApp
というクラスはStatelessWidget
の機能を持ち、
ウィジェットとしてFlutterのUIを構築する機能を持つわけです。
また上で記載したオーバーライドも利用して、build
メソッドを上書きしていることがわかります。
以上が、Flutterでの例でした。
まとめ
本記事では、Flutter / Dart での extends
の役割について解説しました。
いかがだったでしょうか。
上手く使えば、メソッドの共用化ができるテクニックとなっています。
またFlutter 等の内部コードを読む際に欠かせない知識でもあります。
ちょっと難しいテーマでしたが、
ぜひ本記事を参考にして、理解を深めてみてください!
本記事があなたのアプリ開発の一助となれば幸いです。
参考
編集後記(2022/10/14)
extends
についての記事でした。
記事途中の注釈でも書きましたが、extends
の訳を『拡張』と訳すか、
『継承』と訳すかは悩みどころでした。
なので、記事を書くにあたってのTwitterアンケートもやってみました。
(2022年10月14日20:00現在投票受付中です。
ぜひあなたのご意見もお聞かせください。)
記事を書いてる現在だと、いい勝負となっています。
個人的には辞書的に正しい訳の『拡張』が好みですが、
『継承』も実装でやりたいこととしては間違えてはいないし、
おそらく『継承』といったほうが他の言語を触っている人からすると、
理解しやすいのかな、とも思います。
これを『継承』と訳した大元をみつけて、
なぜそう訳したのか確認してみたいです。
ご存じの方いれば、ぜひTwitter等でご教授いただければと思います。
週刊Flutter大学では、Flutterに関する技術記事、Flutter大学についての紹介記事を投稿していきます。
記事の更新情報はFlutter大学Twitterにて告知します。
ぜひぜひフォローをお願いいたします。