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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Flutter

Flutterは、iOSとAndroidのアプリを同じコードで開発するためのフレームワークです。オープンソースで開発言語はDart。双方のプラットフォームにおける高度な実行パフォーマンスと開発効率を提供することを目的としています。

Dart

Dartは、Googleによって開発されたJavaScriptの代替となることを目的に作られた、ウェブ向けのプログラミング言語である。

Q&A

解決済

1回答

1703閲覧

Genericsの使い方につきまして

mako_0221

総合スコア87

Flutter

Flutterは、iOSとAndroidのアプリを同じコードで開発するためのフレームワークです。オープンソースで開発言語はDart。双方のプラットフォームにおける高度な実行パフォーマンスと開発効率を提供することを目的としています。

Dart

Dartは、Googleによって開発されたJavaScriptの代替となることを目的に作られた、ウェブ向けのプログラミング言語である。

0グッド

0クリップ

投稿2022/05/09 06:56

不明点

以下のコードにおきまして、class RandomWordsState extends State<RandomWords> { //hereのうちState Classに指定している型の<RandomWords> Generics記法について、理解することができません。

Dart

1//不明なGenerics 2import 'package:flutter/material.dart'; 3import 'package:english_words/english_words.dart'; 4 5void main() => runApp(MyApp()); 6 7class MyApp extends StatelessWidget { 8 9 Widget build(BuildContext context) { 10 return MaterialApp( 11 title: 'Startup Name Generator', 12 home: RandomWords() 13 ); 14 } 15} 16 17class RandomWords extends StatefulWidget { 18 19 RandomWordsState createState() => new RandomWordsState(); 20} 21 22class RandomWordsState extends State<RandomWords> { //here 23 final _suggestions = <WordPair>[]; 24 final _biggerFont = const TextStyle(fontSize: 18.0); 25 26 Widget build(BuildContext context) { return Scaffold( 27 appBar: AppBar( 28 title: Text('Startup Name Generator'), 29 ), 30 body: _buildSuggestions(), 31 ); 32 } 33 Widget _buildSuggestions() { 34 return ListView.builder( 35 padding: const EdgeInsets.all(16.0), 36 itemBuilder: (context, i) { 37 if (i.isOdd) return Divider(); 38 39 final index = i ~/ 2; 40 if (index >= _suggestions.length) { 41 _suggestions.addAll(generateWordPairs().take(10)); 42 } 43 return _buildRow(_suggestions[index]); 44 }); 45 } 46 Widget _buildRow(WordPair pair) { 47 return ListTile( 48 title: Text( 49 pair.asPascalCase, 50 style: _biggerFont, 51 ), 52 ); 53 } 54}

私が理解している、下記のように、DartにおけるGenericsはクラス定義時にGenericsとして任意の<T>等を指定することで、定義時は型指定に汎用性を持たせたうえで、インスタンス作成時に利用することで、コンパイルエラー(IDEが通知)として安全に利用できるものと理解・整理しておりました。

Dart

1//知っているGenerics 2abstract class User<T> { 3 final T callName; 4 User(this.callName); 5 6 void call(); 7} 8 9class SingleUser<T> extends User<T> { 10 SingleUser(T callName) : super(callName); 11 12 void call() { 13 print('call SingleUser'); 14 print(callName); 15 } 16}

ご質問

ここで、冒頭の不明なGenericsのコードに戻りますが、<RandomWords>は任意の<T>とは違って、具体的に自分で定義しているクラスでもあり、記法や意味合いも私が知っている後段のGenericsSingleUser<T> extends User<T>とは異なるように思えます。
<RandomWords>はそもそもGenericsではないのでしょうか?
もしくはGenericsであっても、後段にある記法以外に用途や利用法があるのでしょうか?
具体的にどのような記法でどのような意味合いであるのか、ご存じの方がいればアドバイスをいただけますと幸いです。
宜しくお願い申し上げます。

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

class クラス名<T>Function<T>(こちらは関数の型定義)に書かれているTが、Genericsでいう型引数になります。
クラスや関数定義中にある同一型相当の名称がその型引数が使われます。
そこに定義されていないものは、他の実際の型が割り当てられるようです。

class SingleUser<T> extends User<T>SingleUser<T>に書かれているTが型引数で、User<T>SingleUser<T>を使用する場合に<>内に書かれた型を当てはめ使用すます。

次にclass RandomWordsState extends State<RandomWords>RandomWordsStateはGenericsなクラス定義ではなく型引数は存在しません。そのため、 State<RandomWords>は事前に定義されているRandomWordsをあてはめ使うことになります。

最後に上では書かれていませんが、class Hoge<T> extends Base<ClassA>という定義の場合、Hoge<T>はGenericsでTという型引数を持っています。しかしBase<ClassA>の方はHogeで指定したTという型引数を使用していません。そのためBaseのGenericsクラスにClassAという型をあてはめたものを使用するといった形になります。

投稿2022/05/09 23:54

編集2022/05/10 06:52
ta.fu

総合スコア1667

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mako_0221

2022/05/10 04:25

ta.fu様 いつも、コメントを頂きありがとうございます。 >次にclass RandomWordsState extends State<RandomWords>はRandomWordsStateはGenericsなクラス定義ではなく仮型パラメータは存在しません。そのため、 State<RandomWords>は事前に定義されているRandomWordsをあてはめ使うことになります。 正直、この部分が理解することができませんでした。つまり、このダイヤモンド演算子で囲まれたRandomWordsはGenericsとは関係がないということでしょうか? ともすれば、「A tour of the Dart language」で該当の文法を説明する箇所を見つけることができないのですが、どこの領域を学ぶことがこの該当箇所のコードの理解につながりますでしょうか? 重ねて申し訳ございませんが、 宜しくお願い申し上げます。
ta.fu

2022/05/10 07:44

class RandomWordsStateはGenericsじゃない普通のクラスの宣言です。 そして、extendsで派生させたいスーパークラスの型がState<RandomWords>になるというだけです。 こちらの方はList<int>とかと同じような感じで、Stateの型引数にRandomWordsクラスを割り当てたクラスという意味です。 なお該当する部分は「A tour of the Dart language」に具体的には書かれていないようです。 仕様書の方は、あっちこっち飛んでるようで、ここだという個所は探せませんでした。 回答中の「仮型パラメータ」を「型引数」に変更しました。 宣言しているところは「仮型パラメータ:type parameters」、使っている場所は「型引数:type arguments」の様な気はするんですが、ちょっと自信はないんで、よく使われている「型引数」で合わせました。
mako_0221

2022/05/10 08:03

ありがとうございます。「普通のクラスの宣言」ということで理解いたしました。 内部的にどのような手続が行われいるのか、コードからはわからなかったので探しておりましたが↓の記事で少し理解をすることができてきました。 https://tech-rise.net/why-stateful-widget-separates-two-classes/ ただ、上記の示したコードでclass RandomWordsのプロパティをRandomWordsStateでアクセスすることはないため、<RandomWords>を宣言しなくとも特にコンパイルエラーにはならないことがわかりました。 ただ、初心者なもので、クラス<型>であるとすればクラスと型の違いは一体何なのだろうと違う森に迷い込んできました。ご提示のようにList<int>であれば、あーリストの要素はintの特性を有しているんだなとわかるのですが、自己定義クラス<自己定義クラス(型?)>になると、どいういうことだ?とちょうど考えを巡らせているところでした。 型引数の表現につきまして、承知を致しました。まだ厳密な違いは分かりませんが、記憶にとどめます。
mako_0221

2022/05/11 00:58 編集

申し訳ございません、クラスと型の関係がやはり混乱してしまったのですが、例えば下記のようにPersonクラスにGeneralと言う型を定義して与えたいとします。そしてPersonと言うクラスを承継してGeneral型を持つクラスMenを定義してそのインスタンスを作成した場合、インスタンスのmanにおいて、men.bについては以下のエラーでアクセスすることができません。これはそもそもクラスや型の使い方や概念を間違えて捉えているのでしょうか? class Person<General> { final a = "test"; } class General { final b = "test2"; } class Man extends Person<General> { } void main (){ var man = Man(); print(man.b); } Error: Line 16 • The getter 'b' isn't defined for the type 'Man'. (view docs) Try importing the library that defines 'b', correcting the name to the name of an existing getter, or defining a getter or field named 'b'
ta.fu

2022/05/11 02:31

多分、やっぱりわかってないんじゃないかなと思います。 実際書くとこんな感じかな。 class Person<General> { Person(this.a); final General a; } class General { final b = "test2"; } class Man extends Person<General> { Man(a) : super(a); } void main(List<String> arguments) { var man = Man(General()); print(man.a.b); } Flutter/Dart関連は、詳細のドキュメントと簡易ドキュメント間の情報の開きが大きすぎるのかなと思います。 簡単に使う場合は簡易ドキュメントでいけるんですが、そのちょっと上を求めようとすると公開されている公式の情報がとたんに少なくなる感じがします。 そこいらの層にいる人は他の言語(Java/C#等)からの移行組で言語の基礎がある程度わかっているとか、探し方が分かっている人なんじゃないかな。 ジェネリック関連でいうと、言語は違いますがそれなりに似ているという意味で概念だけ理解しようと思うのであればMicrosoftのC#が良いのかな。例題交えているんでわかりやすいと思いますよ。 https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/generics/generic-type-parameters
mako_0221

2022/05/11 06:10 編集

コメントを頂き、ありがとうございます。 はい、ご指摘の通り他言語から学び始めた訳ではなく(経験があるのはPHP/JS程度)なので、クラスやオブジェクト指向自体がFlutterやDartをやりながら学んでいると言う状況です。従って、問題を解決するためのアプローチもまだまだ初心者であり、想像力や想定力もないため、稚拙な問いについてもコメントいただけることに感謝しております。上記も、StatfulWidgetのプロパティにアクセスする場合には、State側ではwidget.propで簡単にアクセスできるのでもっと安易に考えておりました。 恐らくこれを容易にできるようにState<RandomWords>とすることでFlutterが実装しているのであるとおもいますが、少し反れますので一旦これは置かせていただきます。 やはり、根本的な理解として以下のコードのような、クラスと型の関係が理解できていないことに気付かされました。 ①List<Int> ②State<RandomWords> ①であれば、Listクラスでは複数の要素を並列的に扱えるクラスで、Built-in Typesで定義されているInt型だけがその要素として扱えますよと言うように直感的に理解できます。 ②のように、自己定義したクラスを型に持って来られると、直感的に何が起きているのか理解ができなくなってしまいます。 そこで、最後にわがままなお願いなのですが、クラスと型の関係を適切に理解できるドキュメンテーションや言語のようなものがあれば教えていただけますでしょうか? 「型 クラス 違い」のようなもので検索しても、なかなか上記のコードを理解するために必要に記事に巡り会えず、お願いをさせていただいている次第です。 何卒、よろしくお願い申し上げます。
ta.fu

2022/05/11 07:52

万人に適切に理解できる文書というのはないでしょうね。 正しく知りたいというのであれば結局Dartの言語仕様書読み解くしかなく、なんとなくでもまずは使えるようにというのであれば「A tour of the Dart language」を覚えて、何かやってエラーが出たらそのエラーメッセージを読み解いて理解していくという感じじゃないでしょうか。 また個人的にWEB上の文書は細切れ感があり、知識なしの状態から覚えるものには向かないと思ってます。 なんでもいいんで、書籍を購入しそれを通しで見たほうが良いんじゃないかな。 あとオブジェクト指向言語とは、について知りたいのであれば、C#,C++,Javaとかの方が言語として古いんで、日本語の書籍(良書があると思うので)を見て、そちらを先に覚えるというのも手かもしれません。
mako_0221

2022/05/11 09:42

有難うございます。承知を致しました。 現状はトライアンドエラーで進めながら学んでいきたいと思います!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問