質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.59%

Flutter, "Widget build(BuildContext context) {}" の冒頭Widgetはなぜ明示的に記述するのか

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,803

score 75

Flutter新規プロジェクトを作成したときに生成されるデフォルトmain.dartのbuildメソッドについて。

■調査した内容
以下の公式ドキュメントやMedium投稿等を読みましたが、直接的に当質問に対応する箇所が見当たりませんでした。概念は理解したのですが、実体的な理解までは至っておりません。

Widget — State — BuildContext — InheritedWidget(Medium)
Widget class
Introduction to widgets
BuildContext class
build method

■現状の理解
画面描画するときにこのbuildメソッドを使うんだな、という程度のグラグラな認識です。

■質問
1) 冒頭のabstract class "Widget" (だけ?)はなぜ明示的に宣言されているのですか?一応、"Widget"部を削除してもコードが正常動作することは確認しました。

2) build(BuildContext context)は、abstract class BuildContextとcontextがbuildメソッドの引数という構造でしょうか?

3) 上記、各トークンの意味を踏まえ、この@override、Widgetクラス、buildメソッドを平易な表現でご解説いただけると大変ありがたいです。どうぞよろしくお願い申し上げます。

@override
Widget build(BuildContext context){
 return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(        
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+3

質問の順序が前後しますが、回答します

2

 build(BuildContext context)は、abstract class BuildContextとcontextがbuildメソッドの引数という構造でしょうか?

  • これはBuildContext型の引数contextbuildメソッドの引数で、引数としては一つです

この質問から、質問者さんは静的型付け言語にあまり多く触れられたことがないかと推察いたしますが、
静的型付け言語では基本的に変数などを<クラス(型)名> <変数名>と宣言します。

dartは、コード的にはjavascriptのような形で、部分的にクラス(型)名を書かなくても動作するようになっていますが、これは動的型付けだからではなく、型推論のある静的型付け言語だからです。

まず、dartの仕様を読んでみることをお勧めします

  • https://www.dartlang.org/guides/language/language-tour[Dart Language Tour]

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及びその子クラスを拡張してクラスとして作成します
  • StatelessWidgetStatefulWidgetWidgetの子クラスです
  • したがって、StatelessWidgetを拡張して作ったクラスも間接的にWidgetの子クラスと言えます
  • buildクラスはそのクラスを画面描画するときにFlutterのフレームワークが呼び出してくれるメソッドです。
  • ここで描画したいものをreturnすることで、画面にパーツが描画されます。

以上、変に複雑になりましたが回答とさせていただきます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/07/11 17:28

    完璧なご回答をいただいたことに、私のミスで今まで気付きませんでした。大変申し訳ございません。お察しの通り、私のような初心者の分かりにくい質問に対してもわかりやすくお教えいただき、誠にありがとうございました。また質問者が最適な順序で理解できるようにご回答も再構成してくださったので、とても読み進めやすかったです。改めてお詫び申し上げるとともに、丁寧なご回答に深く感謝申し上げます。m(_ _)m

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る