質問の順序が前後しますが、回答します
2
build(BuildContext context)は、abstract class BuildContextとcontextがbuildメソッドの引数という構造でしょうか?
- これは
BuildContext型の引数contextがbuildメソッドの引数で、引数としては一つです
この質問から、質問者さんは静的型付け言語にあまり多く触れられたことがないかと推察いたしますが、
静的型付け言語では基本的に変数などを<クラス(型)名> <変数名>と宣言します。
dartは、コード的にはjavascriptのような形で、部分的にクラス(型)名を書かなくても動作するようになっていますが、これは動的型付けだからではなく、型推論のある静的型付け言語だからです。
まず、dartの仕様を読んでみることをお勧めします
1
冒頭のabstract class "Widget" (だけ?)はなぜ明示的に宣言されているのですか?
これにはまず@overrideの説明をします。
記載のあるbuildメソッドは、おそらく
class <クラス名> extends StatelessWidget
か
class <クラス名> extends State<クラス名2>
のような宣言をされたクラス内で定義されたメソッドであるはずです。
ここでextendsはクラスの拡張を示していて、
一般的に、上の例ではStatelessWidget, 下の例ではState<クラス名2>を 親クラス と言います。
それと対応して例で定義されている<クラス名>というクラスは 子クラス と言います。
子クラスは基本的に親クラスに定義されたメソッドを受け継いで持っており、
@overrideが記載されているメソッドというのは、親クラスに定義されたメソッドを上書きしますよ、という宣言です。
@overrideは無くてもメソッド宣言が親クラスにあるものと一致していれば勝手に上書きになるのですが、きちんとつけておくことで何かと便利なのでつけます。
@overrideがついているのにも関わらず、親クラスに同名のメソッドがない時などに、警告を出してくれたりします。
親クラスのメソッドを上書きしたつもりが、誤字で上書きできていなかったケースなどに気づけます。
さて、ここから冒頭のWidgetの戻り値の型宣言がなぜ明示的にされていて、
かつ消しても動いたかについてですが、
dartではメソッドの戻り値の型宣言を省略すると、通常dynamicという特殊な型を戻り値とします。
(ざっくり言うと戻り値の型がなんでも良いという状態です。詳しくはdartの言語仕様を確認してください。)
dartでは仕組み上、1つのクラス内に同じ名前のメソッドを複数持つことができません。
(例えばJavaではメソッド名が異なっても、引数の個数や型などが違う複数の同名メソッドを持つことができます)
少し複雑になりましたが整理すると
extendsキーワードでクラスを拡張すると、子クラスは親クラスと同じメソッドをデフォルトで持っていることになる
- dartでは1つのクラス内に同じ名前のメソッドを複数持つことができない
という点が重要で、Widgetの宣言を消したときに起こっているのは
- 普通は戻り値の型の指定がない場合は
dynamicが戻り値の型とされる
- だが、今回は親クラスに同名のメソッド(
build)があるため、子クラスにもデフォルトで引き継がれている
- 1つのクラス内に
dynamic型を返すbuildメソッドとWidget型を返すbuildメソッドは同居できないので、親クラスの宣言が有効とされた
- したがって、明示的に書いていなくとも、
buildメソッドはWidget型を返すものとして解釈され、Flutter全体としてもエラー無く動作した
です
3
上記、各トークンの意味を踏まえ、この@override、Widgetクラス、buildメソッドを平易な表現でご解説いただけると大変ありがたいです。
@overrideは上でも説明した通り、親クラスのメソッドを上書きしますよという宣言です
- なくても動きますが、便利なのと、お作法的にきちんと書くことがほとんどです。
Widgetクラスは、flutter内では画面に描画するものの基本単位となるクラスです。
- 画面に表示するものは
Widget及びその子クラスを拡張してクラスとして作成します
StatelessWidget, StatefulWidgetもWidgetの子クラスです
- したがって、
StatelessWidgetを拡張して作ったクラスも間接的にWidgetの子クラスと言えます
buildクラスはそのクラスを画面描画するときにFlutterのフレームワークが呼び出してくれるメソッドです。
- ここで描画したいものを
returnすることで、画面にパーツが描画されます。
以上、変に複雑になりましたが回答とさせていただきます。
2019/07/11 08:28