Chapter 03

Day2: Dartの基礎2(関数・クラス), Hello world

fastriver
fastriver
2021.02.13に更新

Dart入門(続き)

前回に引き続きDartの基礎を学んでいきます。

各セクションで学んだことを元に、ログインのようなシステムを構築していく演習を用意しているので是非手を動かしながら読んでいきましょう。(↓のコードが初期状態)

void main() {
	String name = "福沢諭吉";

	if(name != "福沢諭吉") {
		print("ログインできません");
	}
	else {
		print("ようこそ! $name さん");
	}
}

関数

関数(function)とは、一連の処理をまとめ、何回でも呼び出せるようにしたものである。
複数回呼ぶ処理をまとめて記述を簡潔にするだけでなく、処理に名前をつけて意味づけするといった用途にも使われる。

数学にも関数という言葉があるが、数学の関数はプログラミングで言う「引数あり・返り値あり」の関数がそれに相当する。

void main() {
	showEmoji(); // -> 👽

	greeting("fastriver"); // -> こんにちは、fastriver さん

	int result = factrial(5);
	print(result); // -> 120
}

//引数なし・返り値なしの関数
void showEmoji() {
	print("👽");
}

//引数あり・返り値なしの関数
void greeting(String name) {
	print("こんにちは、$name さん");
}

//引数あり・返り値ありの関数
int factrial(int value) {
	int result = 1;
	for(int i = 1; i <= value; i++) {
		result = result * i;
	}
	return result;
}

DartPadで見る

関数定義は、

[返り値の型] [関数名]([引数]) {
[関数の内容];
return [返り値];
}

の形で行う。関数の中で関数を定義することはできない。

演習: ログイン処理を関数にまとめてみる

void main() {
	login();
}

void login() {
	String name = "福沢諭吉";

	if(name != "福沢諭吉") {
		print("ログインできません");
	}
	else {
		print("ようこそ! $name さん");
	}
}

関数名

変数と同様好きな名前をつけていい。ただし変数名とも合わせて同じ名前を複数定義してはいけない。数字を先頭にするのもNG。

関数の返り値(戻り値)

整数を返すならint、文字列ならStringのように書く。

何も返さない場合はvoidと書く

return文を書くことで、関数から値を返すことができる。return文が実行されるとその時点で関数の処理は終了する。

String hoge(int value) {
	if(value >= 10) {
		return "$value は10以上だね!";
		//ここは実行されない
		//
		//
	}

	return "$value は10未満";
}

関数の返り値は変数と同じように扱える。

void main() {
	String fuga = hoge(20); //変数に代入できる
	print(fuga); // -> "20は10以上だね!"

	print(hoge(5)); //そのまま関数の引数にも突っ込める
	// -> "5は10未満"
}

もちろんmainもprintも関数

DartPadで見る

演習: 結果は別に処理するようにする

void main() {
	bool result = login();
	if(result) {
		print("ようこそ!");
	}
	else {
		println("ログインできません");
	}
}

bool login() {
	String name = "福沢諭吉";

	if(name != "福沢諭吉") {
		return false;
	}
	else {
		return true;
	}
}

引数(ひきすう, Parameter)

演習: 名前は色々試せたほうがいいよね

void main() {
	bool result = login("福沢諭吉");
	if(result) {
		print("ようこそ!");
	}
	else {
		println("ログインできません");
	}
}

bool login(String name) {
	if(name != "福沢諭吉") {
		return false;
	}
	else {
		return true;
	}
}

関数は引数を使って値を受け渡しする。

([1つ目の型名] [1つ目の引数名], [2つ目の型名] [2つ目の引数名] ...)

引数は関数名の後、カッコ内に型名+引数名の順で書く。複数ある場合はコンマ区切りで続ける。

引数に値を渡すときは定義の順にコンマ区切りで一つづつ値を入れていく。引数の数が合わないとエラーを吐くので注意。

引数がない場合は空のカッコを関数名のあとに付ける。省略はできない。

引数で定義した変数には渡された値が入り、その関数内のみで使える。

void main() {
	int x = add(age(),3);
}

int age() {
	return 19;
}

int add(int a, int b) {
	return a+b;
}

DartPadで見る

演習: せっかくなのでパスワードも聞いてみる

void main() {
	bool result = login("福沢諭吉", "keiolove");
	if(result) {
		print("ようこそ!");
	}
	else {
		println("ログインできません");
	}
}

bool login(String name, String password) {
	if(name != "福沢諭吉") {
		return false;
	}
	if(password != "keiolove") {
		return false;
	}
	return true;
}

名前付き引数

引数を記述する時、引数を中括弧{}で囲むと名前付き引数(Named Parameter)として使えるようになる。

([普通の引数] ... , { [名前付き引数1], ... })

呼び出す時:
[名前付き引数]: [値]

名前付き引数は関数を呼び出す時名前を指定して引数に値を入れることができる。逆に普通の引数のような順番には影響されない

void main() {
	//名前付き引数は無視して普通に呼び出す
	//この場合middleを評価するとnullとなる
	print(fullName("Yuki", "Hayakawa"));
	
	//名前付き引数は必ず最後に置く(普通の引数優先)
	print(fullName("Yuki", "Hayakawa", middle: "buffalo"));
}

String fullName(String first, String last, {String middle}) {
	if(middle != null) { //nullじゃないことを確認しよう
		return last + " " + middle + " " + first;
	}
	else {
		return last + " " + first;
	}
}

DartPadで見る

引数のデフォルト値

名前付き引数はもし値が渡されなかった場合に使うデフォルトの値を指定することができる。

void main() {
	//値を渡さない場合、デフォルト値で評価される
	print(fullName("Yuki", "Hayakawa")); // -> Hayakawa Thomas Yuki
	
	//渡された値が使われる
	print(fullName("Yuki", "Hayakawa", middle: "buffalo"));
}

String fullName(String first, String last, {String middle = "Thomas"}) {
	return last + " " + middle + " " + first;
}

DartPadで見る

演習: 任意でニックネームを設定する

void main() {
	bool result = login("福沢諭吉", "keiolove");
	if(result) {
		print("ようこそ!");
	}
	else {
		println("ログインできません");
	}
}

bool login(String name, String password, {String nickname = "名無し"}) {
	if(name != "福沢諭吉") {
		return false;
	}
	if(password != "keiolove") {
		return false;
	}
	print("ニックネーム $nickname で登録します");
	return true;
}

再帰関数

関数は再帰的に呼び出す(その関数の中から呼ぶ)ことができる。

void main() {
	print(factrial(5)); // -> 120
	print(factrial(7)); // -> 5040
}

// 階乗を計算する
int factrial(int value) {
	if(value <= 1) { //無限ループにならないようすぐ値の返る選択肢は必要
		return 1;
	}
	else {
		return value * factrial(value - 1); //1小さい数の計算結果に今の数を掛ければ求まる
	}
}

DartPadで見る

演習

  • 1から引数に指定した数までを足した値を返す関数を作ってみる
  • 名前付き引数を用意して開始の数字を指定できるようにしてみる
  • n段飛ばしで足し算できるようにしてみる

解答例はこちら

クラス(class)

本当に上辺しか話さないので少し詳しく知りたい人はここを読みましょう「世界一わかりやすくクラスとインスタンスを説明する」

概念

Dartの変数・関数・その他諸々は全てオブジェクト(Object)である。

Everything you can place in a variable is an object, and every object is an instance of a class. Even numbers, functions, and null are objects. All objects inherit from the Object class. -A tour of the Dart language

全部です、全部

classはobjectを作るためのテンプレートのようなもので、classからobjectを作ることをインスタンス化といい作られたobjectのことをインスタンスと呼ぶ。

なので基本は インスタンス==object

classはテンプレートだということだけ覚えてもらえればよい(objectとかまでこの講義では扱わない)

classはそこからobjectを複数作ることが可能で、かつ作られたobjectは全て独立している(互いに影響しない)

classはメンバ変数とメンバメソッドを持つことができる。

  • メンバ変数(menber variable): オブジェクトが持つデータ。同じクラスでインスタンス化されたオブジェクトは同じ名前のメンバ変数を持つが、中の値は固有になる
  • メンバメソッド(menber method): オブジェクトに対して使える関数。同じクラスでインスタンス化されたオブジェクトは同じ名前のメンバメソッドを持ち、呼び出すことができる

オブジェクトはそれぞれ変数と関数を持ってる

実装の話

見た目だけでも覚えていてくれれば...

class Car { //車クラス
	String _color; //メンバ変数
	String _name;
	int _speed;

	Car(String color, String name, int speed) {
		_color = color;
		_name = name;
		_speed = speed;
	}

	void run() { //メンバメソッド
		//走るのかな
		print("$_name が時速$_speed kmで走るよ!");
	}

	void explode() {
		//爆破するのかな
		print("$_color 色の車が爆破されたよ");
	}
}

void main() {
	//複数のオブジェクトが作られる
	Car redPrius = Car("赤", "プリウス", 50);
	Car bluePrius = Car("青", "プリウス", 100);
	Car greenFit = Car("緑", "フィット", 40);
	
	//それぞれのオブジェクトは同じ関数、違う中身の変数を持つ
	greenFit.run(); // -> フィット が時速40 kmで走るよ!
	bluePrius.run(); // -> プリウス が時速100 kmで走るよ!
	redPrius.explode(); // -> 赤 色の車が爆破されたよ
	greenFit.explode(); // -> 緑 色の車が爆破されたよ
}

DartPadで見る

メンバメソッドは変数名(オブジェクト名)の後ろにドット.を付けて関数名を続ける。
メンバ変数も同様に可能(ただし変数名の最初がアンダースコア_になっているものはオブジェクトの状態ではアクセスできない(プライベートメンバ))

前回やったintやStringもクラスであり、メンバメソッドを使うことができる

void main() {
	//メンバ変数にアクセスして文字の長さを取得
	print("適当な文字列".length); // -> 6
	
	//メンバメソッドで絶対値を取得
	int distance = -500;
	print(distance.abs()); // -> 500
}

DartPadで見る

Flutter Web環境構築

  • Flutter SDKをインストール
  • AndroidStudioをインストール
    • Flutter Pluginを導入
  • Chromeをインストール
  • FlutterのChannelをBetaに変更

前回のから抜粋

できなかった人へ...

実はDartPadでもflutter Webが動かせます

https://dartpad.dev/flutter

Hello, World!

左上の

[File] -> [New] -> [New Flutter Project...] -> [Flutter Application] -> [Next] -> [Next] -> [Finish]

でプロジェクト作成

上の

[No Device Selected] -> [Chrome]

その右の[▷]マークか[🐞]マークで実行

宿題

演習問題やる

環境構築

Day3以降はAndroidStudio+ChromeでFlutter Webが実行できるという体で話が進んでいきます