見出し画像

初めてのプログラミング学習用【Dart(Flutter)】

こんな方におすすめの内容です
・プログラミングの基礎の基礎を知りたい
・プログラミングの用語なんて何一つ知らない
・スマホアプリを作れるようになりたい

「プログラミングを初めて勉強するなら、まずはここから知っていこう!」という内容になっています。
たくさん説明がありますが、暗記は不要ですので気楽に読んでください。
忘れたら何度でも見返せばOKです。プログラミングはカンニングOKなんです。

また、後半に行くほどややこしくなりますが、1発で全て理解するのは天才じゃないと難しいと思います。
何度も繰り返し使っていると、簡単に感じてきますので、今はなんとなくの理解でOKです。

上手く進められない箇所があれば、コメントを残してくだされば、できる限り回答いたします。
お気軽にご質問ください。

では、学習に入りましょう!

プログラミングとは?

コンピュータに命令することをプログラミングといいます。

コンピュータは自分で考えることができないため、一つ一つの動きを順番に書き出す必要があります。

例えばロボットを歩かせたい場合、
「右足を上げる→右足を前に出す→右足を下ろす」
みたいな命令に従ってコンピュータが動きます。

コンピュータは日本語で命令しても理解できないので、コンピュータが理解できる言語で命令する必要があります。それをプログラミング言語と言います。
プログラミング言語はたくさん種類がありますが、このnoteではDartというプログラミング言語を使用します。

簡単なコードを動かしてみよう

実際に簡単なコードを書きながら読み進めてほしいので、DartPadというサイトを使っていただきます。
▶︎ここをクリックしてください
↓このようなサイトが開きます。これがDartPadです。ここにいろんなコードを書いて、実際に動かしていきます。

DartPadの左側のコードを全て消して、下記のコードを書いてください。

void main() {
  print("Hello World");
}

書けたら「▶︎ Run」と書かれているボタンをクリックしてください。
↓のように右上に「Hello World」と表示されていればOKです。

[コードの解説]

Dartのコードを実行するとき、main関数の中に書かれたコードが実行されます。{ }の間に書かれたコードが上から順番に実行されます。下記がmain関数です。↓

void main() {  // ここから
  
}  // ここまでの間がmain関数の中です

Console(DartPadの右上)という場所にデータを表示するためのprint関数というコードがあります。( )の間に書かれたデータが表示されます。下記がprint関数です。↓

print("Hello World");  // ()の間に書かれた「Hello World」がConsoleに表示されます。

変数

変数とは

プログラミングでの変数は「値を入れておく箱」のようなものです。
数学のxやyみたいな変数と同じような意味です。

例えば、下記のようなコードがあったとします。

int a = 1;

このコードは、下のようなことをしています。

下記のコードをDartPadに書いてください。

void main() {
  int a = 1;  // 変数aの中に1を入れる
  print(a);  // 変数aの中身をConsoleに表示する
}

Runをクリックしてコードを実行すると、右側のConsoleに「1」と表示されます。変数「a」の中に「1」が入っていることが分かります。

変数の中には一つしかデータを入れられません。
下記のコードをDartPadに書いて実行してみてください。

void main() {
  int a = 1;  // 変数aの中に1を入れる
  a = 2;  // 変数aの中に2を入れる
  print(a);  // 変数aの中身をConsoleに表示する
}

右側のConsoleに「2」と表示されます。変数「a」の中に「1」が「2」に入れ替わっています。

上の例では変数に整数を入れていますが、整数以外にも少数や文字など、いろんな変数があります。

変数は中に入れるデータの形によって、があります。
ここからはいろんな型の変数を紹介していきます。

int型

整数を入れる箱です。
↓例

int number = 100;

int(整数の箱)に
numberという名前を付けて
「100」を入れています。

double型

小数を入れる箱です。
↓例

double number = 1.5;

double(小数の箱)に
numberという名前を付けて
「1.5」を入れています。

String型

文字列を入れる箱です。
↓例

String greeting = 'Hello World';

String(文字列の箱)に
greetingという名前を付けて
「Hello World」を入れています。
文字列は「'」か「"」で挟む必要があります。

boolean型

プログラムの中で正しいor間違いを判定することがあります。
↓のコードをDartPadに入力して、Runで実行してみてください。

void main() {
  print(1 == 1);
}

DartPadの右側のConsoleに「true」と表示されます。
「true」は正しいという意味です。

上のコードの「==」は、「==」の右側と左側が同じかどうかを判定するものです。
この場合は、右も左も「1」で同じなので、正しいという意味の「true」となります。

今度は下記のコードをDartPadで実行してみてください。

void main() {
  print(1 == 2);
}

Consoleに「false」と表示されます。
「false」は間違いという意味です。
「1」と「2」は同じではないので、「false」が表示されます。

この「true」と「false」を日本語で「真偽値」と言います。
そして、「true」か「false」を入れる箱を「boolean型」と言います。
↓例

boolean result = true;

boolean(真偽値の箱)に
resultという名前を付けて
「true」を入れています。

List型

実は、ここまでで解説した型の変数では、複数のデータを入れることができません。
List型なら複数のデータを一つの変数にいれることができます。
複数のデータが入っている変数を日本語では配列といいます。

↓イメージ

↓コードにするとこうなります。

List fruit = ["りんご", "みかん", "いちご"];

List型の中身には左から順番に、0, 1, 2, …と番号がついています。
上の例では、0→りんご、1→みかん、2→いちご
となります。

List型の変数から一つのデータを取り出したい時、下のような書き方をします。

変数名[番号]

下のコードをDartPadに書いて実行してみてください。Consoleに「りんご」と表示されます。

void main() {
  List fruit = ["りんご", "みかん", "いちご"];
  print(fruit[0]);
}

「0」を「1」や「2」に書き換えて実行して、「みかん」や「いちご」も表示させてみましょう。

Map型

Map型もList型と同じように複数のデータを扱うことができます。

List型と違う点
List型は一つ一つに番号がついています。
Map型は番号ではなく、一つ一つ名前を付けていきます。
↓イメージ

↓コードにするとこうなります。

「apple」「orange」「strawberry」は一つ一つの箱の名前で、キーといいます。
「りんご」「みかん」「いちご」は、その中身のデータです。

Map型の変数から一つのデータを取り出したい時、下のような書き方をします。

変数名["キー"]

下のコードをDartPadに書いて実行してみてください。Consoleに「りんご」と表示されます。

void main() {
  Map fruit = {"apple": "りんご", "orange": "みかん", "strawberry": "いちご"};
  print(fruit["apple"]);
}

「apple」を「orange」や「strawberry」に書き換えて実行して、「みかん」や「いちご」も表示させてみましょう。

演算子

演算子とは

計算をするとき、「+」「-」「×」「÷」といった記号を使いますよね?
これらの記号のことを演算子といいます。

プログラミングでも変数のデータを足したり引いたり色々します。
演算子もたくさん種類があるので、一つ一つ解説していきます。

最初にもお伝えしましたが、覚えなくて大丈夫ですからね。
忘れたら何度でも見返せばいいだけなので。

算術演算子

算術演算子は簡単にいうと、「+」「-」「×」「÷」のような計算するための演算子です。

下記のコードをDartPadに書いて実行してみてください。
計算結果がConsoleに表示されます。

void main() {
  int num = 10; // 変数numに10を入れる
  
  print(num + 1); //足し算

  print(num - 1); //引き算

  print(num * 2); //掛け算

  print(num / 2); //割り算

  print(num % 3); //余り
}

「+」「-」はそのまま
「×」は「*」
「÷」は「/」
を使います。

最後の「num % 3」は「10を3で割ったときの余り」を計算しています。

比較演算子

比較演算子は2つのデータを比較する演算子です。
比較した結果、true(正しい)かfalse(間違い)か判定されます。

下記のコードをDartPadに書いて実行してみてください。
計算結果がConsoleに表示されます。

void main() {
  int num = 10;
  
  print(num > 1); // numが1より大きいならtrue、違う時はfalse

  print(num >= 1);  // numが1以上ならtrue、違う時はfalse

  print(num < 1);  // numが1より小さいならtrue、違う時はfalse

  print(num <= 1);  // numが1以下ならtrue、違う時はfalse

  print(num == 1);  // numが1と同じならtrue、違う時はfalse

  print(num != 1);  // numが1ではないならtrue、違う時はfalse
}

変数「num」に入れた10を書き変えて、Consoleの表示が変わるかどうか試してみましょう。

条件分岐

条件分岐とは

条件によって実行するコードを変えることをいいます。

日常生活に例えると、
「雨が降っていたら電車で行く、雨が降っていなかったら自転車で行く」
みたいなイメージです。

if文

下記のような書き方をします。

if(条件式){
  条件式がtrueの時の処理...
}

下記のコードをDartPadに書いて実行してみてください。
計算結果がConsoleに表示されます。

void main() {
  int num = 10;
  if (num >= 5) {
    print('5以上');
  } 
}

上のコードは変数numが5以上の時は「5以上」と表示します。
今度は下記のコードをDartPadに書いて実行してみてください。

void main() {
  int num = 3;
  if (num >= 5) {
    print('5以上');
  } 
}

Consoleに何も表示されません。
上のコードは変数numに3が入っていて、5以上ではありません。
そのため、「print('5以上');」のコードが実行されませんでした。

if...else文

下記のような書き方をします。

if(条件式){
  条件式がtrueの時の処理...
}
else{
  条件式がfalseの時の処理...
}

下記のコードをDartPadに書いて実行してみてください。
計算結果がConsoleに表示されます。

void main() {
  int num = 6;
  if (num >= 5) {
    print('5以上');
  } 
  else {
    print('5未満');
  } 
}

変数numは6なので「print('5以上');」が実行されて、「5以上」と表示されます。
今度は下記のコードをDartPadに書いて実行してみてください。

void main() {
  int num = 4;
  if (num >= 5) {
    print('5以上');
  } 
  else {
    print('5未満');
  } 
}

変数numは4なので「print('5未満');」が実行されて、「5未満」と表示されます。

else if

下記のような書き方をします。

if(条件式A){
  条件式Aがtrueの時の処理...
}
else if(条件式B){
  条件式Bがtrueの時の処理...
}
else if(条件式C){
  条件式Cがtrueの時の処理...
}
else{
  条件式A,条件式B,条件式Cが全てfalseの時の処理...
}

下記のコードをDartPadに書いて実行してみてください。

void main() {
  int num = 3;
  if (num >= 10) {
    print('10以上');
  } else if (num >= 5) {
    print('5以上');
  } else if (num >= 0) {
    print('0以上');
  }
  else {
    print('0より下');
  }
}

「num >= 10」がfalse
「num >= 5」もfalse
「num >= 0」はtrueなので、「print('0以上');」が実行されて、「0以上」と表示されます。

関数

ここから難しさが上がってきます。
最初は何となくでいいので、目を通していただけたらと思います。
アプリを作る時に何度も出てくると思うので、その度に復習していただければ、徐々に理解が進むかと思います。

関数とは

処理をまとめたプログラムの部品のようなものです。
と言われてもよく分からないと思うので、まずは下記のコードを見てください。

void main() {
  print('今日は');
  print('学校で勉強');
  print('放課後は部活');
  print('ーーーー');
  
  print('明日も');
  print('学校で勉強');
  print('放課後は部活');
  print('ーーーー');
  
  print('明後日は');
  print('休みなので一日中寝てる');
}

今日と明日の内容が同じなので、関数にまとめます。
下記のように書き換えることができます。

void main() {
  print('今日は');
  heijitu();
  print('ーーーー');
  
  print('明日も');
  heijitu();
  print('ーーーー');
  
  print('明後日は');
  print('休みなので一日中寝てる');
}

void heijitu() {
  print('学校で勉強');
  print('放課後は部活');
}

「heijitu」という名前の関数を作って、平日の内容をまとめて使い回せるようになります。

このように同じような処理をまとめて使い回せるのが関数です。
関数にもいくつか種類があるので、解説していきます。

void型:引数なし

上で紹介したように処理をまとめただけの関数です。
下記のような書き方をします。

void 関数名() {
  まとめたい処理を書く
}

下記のコードをDartPadで実行してみてください。

void main() {
  total();
}

void total() {
  print(30 + 60);
}

「total」関数を作って、30 + 60を計算してConsoleに表示する処理を書いています。
その「total」関数を2行目で呼び出して使っています。

void型:引数あり

下記のような書き方をします。

void 関数名(型 引数1, 型 引数2) {
  引数1と引数2を使った処理を書く
}

下記のコードをDartPadで実行してみてください。

void main() {
  total(40, 50);
}

void total(int taro, int jiro) {
  print('太郎と次郎の合計点');
  print(taro + jiro);
}

「total」関数で太郎と次郎の点数を受け取れるように、「taro」「jiro」という名前とつけた引数を用意します。
2行目で呼び出した「total」関数に太郎と次郎の点数を渡すことで、2人の合計点を計算させます。
↓データの動き方

return型:引数なし

return型では処理した結果をデータに変換します。
下記のような書き方をします。

型 関数名() {
  まとめたい処理を書く
  return 処理した結果のデータ
}

下記のコードをDartPadで実行してみてください。

void main() {
  int totalPoint = getTotal();
  print(totalPoint);
}

int getTotal() {
  int total = 30 + 60;
  return total;
}

「getTotal」関数では30+60の計算結果90を、変数「total」に入れて、変数「total」をreturnしています。
この「getTotal」関数を呼び出すと、変数「total」に変換されます。つまり90に変換されます。
↓データの動き

return型:引数あり

受け取った引数を使って処理をして、その結果に変換する関数です。
下記のような書き方をします。

型 関数名(型 引数1, 型 引数2) {
  引数1,引数2を使って処理する
  return 処理した結果のデータ
}

下記のコードをDartPadで実行してみてください。

void main() {
  int totalPoint = getTotal(50, 60);
  print('太郎と次郎の合計点');
  print(totalPoint);
}

int getTotal(int taro, int jiro) {
  int total = taro + jiro;
  return total;
}

「getTotal」関数で太郎と次郎の点数を受け取れるように、「taro」「jiro」という名前とつけた引数を用意します。
2行目で呼び出した「getTotal」関数に太郎と次郎の点数を渡すことで、2人の合計点110に変換されて、変数「totalPoint」に入ります。
↓データの動き方

非同期処理

ここはとても難しいです。初めての方にはなかなか理解しづらいと思います。
今は「そういうものがあるんだなぁ」くらいで結構です。
アプリを作る時に何度も出てくると思うので、その度に復習していただければ、徐々に理解が進むかと思います。

非同期処理とは

今まで紹介してきたコードは一つずつ順番に処理されます。これは同期処理と言います。
そうではなく、複数の処理を同時に行うのが非同期処理です。

↓こんなイメージです

下記のコードをDartPadで実行してみてください。

void main() {
  print('処理1');
  // ↓2秒待った後に print('処理2'); を行う
  Future.delayed(Duration(seconds: 2)).then((result) {
    print('処理2');
  });
  print('処理3');
}

Consoleの内容は
処理1
処理3
処理2
という順番になります。
処理の流れを図にするとこんなイメージです↓

非同期関数とは

非同期関数とは、非同期な処理を含む関数のことです。
↓例

Future<void> future() async {
  // ↓2秒待った後に print('処理'); を行う
  await Future.delayed(Duration(seconds: 2));
  print('処理');
}

非同期関数を作るには「Future<型>」で関数の型を宣言し、「{}」の前に「async」を追加します。

非同期関数(void型)

非同期処理を含むvoid型の関数です。
下記のような書き方をします。↓

Future<void> 関数名() async {
  await 非同期処理;
}

非同期関数(return型)

非同期処理を含むvoid型の関数で、処理が終わったら結果をデータに変換します。
下記のような書き方をします。↓

Future<型> 関数名() async {
  await 非同期処理;
  return 結果のデータ;
}

クラスとインスタンス

クラスとは

クラスとはどんなものかを表した設計図のようなものです。
例えば、ゲームの中にモンスターが出てくるとします。
モンスターの設計図としてモンスタークラスを考えます。
↓こんな感じです

モンスタークラス(モンスターの設計図)
・「体力」がある
・「攻撃力」がある
・「攻撃する」という行動ができる

クラスの書き方↓

class クラス名 {
  final 型 変数名1;
  final 型 変数名2;

  クラス名({required 変数名1, required 変数名2});

  型 関数名() {
    何らかの処理・・・
  }
}

変数名1、変数名2は、クラス(設計図)はどんな情報を持っているかを設定します。
モンスターの体力や攻撃力のような情報です。

関数はクラス(設計図)はどんな行動ができるかを設定します。
モンスターの攻撃するという行動のようなものです。

モンスタークラスをコードにするとこんな感じになります。

class Monster {
  final int hitPoint; // 体力
  final int attackPoint; // 攻撃力
  
  // インスタンス化した時に、体力と攻撃力を設定するためのコード
  Monster({required this.hitPoint, required this.attackPoint});
  
  // 攻撃する行動
  void attack() {
    print('相手に');
    print(attackPoint);
    print('のダメージを与える');
  }
}

インスタンスとは

インスタンスとはクラス(設計図)から生み出された実物のようなものです。
クラスを実物として生み出すことをインスタンス化と言います。
先ほどのモンスタークラスをインスタンス化して実物にします。
↓こんな感じです

モンスターインスタンス(モンスターの実物)
・体力は100
・攻撃力は30
・攻撃する(相手に30のダメージを与える)

モンスタークラスをインスタンス化するコードを書くとこんな感じになります。

// 体力50・攻撃力10のモンスターをインスタンス化して、Monster型の変数「pikachu」に入れる
Monster pikachu = Monster(hitPoint: 50, attackPoint: 10);
// インスタンス化したモンスター「pikachu」に「攻撃する」という行動をさせる
pikachu.atack();

インスタンス化したものを後から使うためには、作ったクラスの型の変数に入れる必要があります。
この場合は、Monsterクラスをインスタンス化したので、Monster型の変数「pikachu」に入れています。

クラスとインスタンスを使ったコードを動かす

Monsterクラスとそのインスタンスを使ったコードを動かしてみましょう。
下記のコードをDartPadに書いて実行してみてください。

void main() {
  // 体力50・攻撃力10のモンスターをインスタンス化して、Monster型の変数「pikachu」に入れる
  Monster pikachu = Monster(hitPoint: 50, attackPoint: 10);
  // インスタンス化したモンスター「pikachu」に「攻撃する」という行動をさせる
  pikachu.atack();
}

// モンスタークラス(設計図)を作る
class Monster {
  final int hitPoint; // 体力
  final int attackPoint; // 攻撃力
  
  // インスタンス化した時に、体力と攻撃力を設定するためのコード
  Monster({required this.hitPoint, required this.attackPoint});
  
  // 攻撃する行動
  void attack() {
    print('相手に');
    print(attackPoint);
    print('のダメージを与える');
  }
}

お疲れ様でした

ややこしい説明をたくさんしてしまい、すみません。
特に後半は難しい内容が多く、読むのを辞めたくなった方も多いのではないでしょうか。
ここまで辿り着いたあなたはすごいと思います!

何度かお伝えしていますが、暗記は不要です。
この内容を1発で全て理解するのは天才じゃないと難しいです。
もっと分かりやすく説明が思いついたら更新していきます。

実際にアプリを作りながら学べる教材も用意する予定ですので、よければ使ってみてください。

最後まで読んでくださり、ありがとうございました!

この記事が気に入ったらサポートをしてみませんか?