■ はじめに
説明
1月から Flutter を学習し始めたのですが、それ以前に Dart の理解は必ず必要な道です。
そこで、基礎的な文法についてまとめてみたのでついでに Qiita にも投稿してみます。
過不足あれば是非ご指摘下さい。
ちなみに Dart は JavaScript に対抗?するために2011年に Google によって作られた言語で、Dart の文法は JavaScript に似ています。又、オブジェクト指向言語であり、静的型付け言語です。
■ 定数
値を変更する事が出来ないものを「定数」と言い、Dart でよく使う定数としては以下の通り2種類ある。
final
- 実行タイミング:インスタンス生成時に代入される定数
- 動的な値を含める事は出来るか:出来る
- 変数を含む事ができるか:可能
- 補足:アプリが実行される段階で値が確定する必要がある。又、const と違い、変数を入れる事が出来る。
const
- 実行タイミング:コンパイル時に代入される定数
- 動的な値を含める事は出来るか:出来ない(上記で説明の通り、コンパイル時に代入されるため)
- 変数を含む事ができるか:不可
- 補足:コンパイル時に値が確定している必要があるため、変数は入れられない。
final と const のまとめ
final
が実行時に初めて値が確定され、const
がコンパイル時に値が確定する。
const
やfinal
を使用することで、変数の値を不変にすることが出来る。
特に const を使用することで、プログラムのメモリ使用量を最適化し、パフォーマンスを向上させることが可能になる。(コンパイル時に値が確定されるため、実行時のリソース消費を削減できる仕組み)
■ データ型や型推論機能(var)に関して
データ型
データ型 | Dart (Flutter) | 例や注意点 |
---|---|---|
文字列 | String | 短い文字列から長い文字列まで対応している。 |
数値(整数) | int | 10 や 20 など。小数点以下を持たない整数値を表現する。 |
浮動小数点 | double | 3.14 や 0.001 など。小数点以下を持つ数値を表現する。 |
真偽値(true / false) | bool | true や false。条件を表現するための値。条件が成り立つかどうかを示す。 |
日付や時間 | DateTime | "2024-02-01", "2024-02-02 14:30:00" など。日付・時間を表現する。 |
配列 | List | 同じ型の要素を複数格納する為に1つにまとめたもの 例: List numbers = [1, 2, 3]; |
ハッシュ | Map | 複数の要素を格納する事が出来る。 List と比べて違う点は、キーとバリューの組み合わせを格納する。 例: Map ages = {'田中': 30, '鈴木': 25}; |
シンボル | Symbol | 軽量なラベルとして使われる。例: #symbol_name |
非同期処理 | Future | 非同期処理を表現するデータ型。時間のかかる操作を非同期に行い、アプリの応答性を向上させる。 |
関数 | Function | コードのブロックで特定のタスクを実行。引数を受け取り、値を返すことも可能。 |
何もない値 | null | オブジェクトが存在しないことを示す特別な値。参照が何もない状態。 |
型推論機能(var)を使ってデータ型を自動で割り当てる方法
varは「バリアブル」の略で、値に入ってる型を見て、自動でデータ型を決めてくれる機能。
通常、変数を宣言する際にはデータ型を直接指定する必要があるが、var を使用することで型推論機能を利用出来る。
- var を使用せず、通常の宣言の場合
String name = 'テスト';
- var を使用した宣言の場合
var name = 'テスト';
まとめ
var
を使用する場合、変数に一度値を割り当てた後は、その変数の型は変更できない。
これは、var
による型推論機能が初期割り当て時にのみ行われ、その後の変数の型は固定されるため。
■ ループ処理
for文
指定された回数だけ繰り返し処理を行う。
- 構文
for (データ型; 条件式; 更新式) {
// 実行する処理
}
- 例
void main() {
for (int i = 0; i < 5; i++){
print ('現在の値は $i ');
}
}
- 初期化: ループ変数を初期化するステートメント。
- 条件: ループが実行される条件。条件がtrueの間、ループが続きます。
- 更新: 各ループ終了後に実行されるステートメント。通常、ループ変数を更新します。
while文
指定された条件が true の間、繰り返し処理を行う。
- 構文
while (条件式) {
// 実行する処理
}
- 例
void main() {
int i = 0;
while (i < 5) {
print('現在の値は $i');
i++;
}
}
この例でも、0から4までの値が順に print
文で出力される。
while
文は初期化や更新を別途行う必要がある。
■ 例外処理
Exception
Exception(例外)は、実行時に発生するエラーや問題に対処するために使う。
-
try
ブロック内で例外が発生する可能性があるコードを囲み、catch
ブロックで例外が発生した場合の処理を書く。 - 例外が発生しなかった場合は、
try
で処理、発生した場合は、catch
で処理を実行する。
- 構文
try {
// 例外が発生する可能性があるコード
} catch (変数名) {
// 例外が発生した場合の処理
}
- これが例外が発生していない場合の処理
void main() {
try {
// 何かしらの処理
var sum = 2 + 3;
print('処理結果: $sum');
print('例外が発生しないパターン');
} catch (e) {
// 例外が発生した場合の処理
print('例外が発生: $e');
}
}
- これが例外が発生した場合の処理
void main() {
try {
// 何かしらの処理
var result = 12 ~/ 0; // あえて例外を発生させるため、0で割り算をする
print('計算結果: $result');
} catch (e) {
// 例外が発生した場合の処理
print('例外が発生するパターン');
}
}
この例では、ゼロで割り算をしようとしているため、catch
ブロックが実行される。
■ 列挙型
enum
enum(列挙型)は、特定の値のセットをまとめて名前を付ける仕組み。
具体的な値は列挙され、それぞれに名前が付与されている。
これにより、特定の値を表現する際にわかりやすい名前を使用出来る。
- 構文
enum EnumName {
Value1,
Value2,
Value3,
// 他の値
}
- 例
ここで、Weekday
は enum の名前であり、Monday
、Tuesday
などが具体的な列挙値。
これにより、プログラム内で Weekday.Monday
のようにして特定の曜日を指定できて、可読性が向上する。
// 曜日を表す enum
enum Weekday {
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday,
}
このようにして、enum を使用することで、特定の値のセットを簡潔かつ分かりやすく表現できる。
void main() {
var today = Weekday.Wednesday;
print(today); // 出力: Weekday.Wednesday
}
■ 静的プロパティ
static
static
はインスタンスを生成せずにクラス自体からアクセスできる変数やメソッドに用いられる。
例えば、下記のようなクラスがあり、name
に入っている'田中さん'という値を取得する場合、通常はインスタンスを作成してからアクセスする必要がある。
- class
class Test {
String name = '田中さん';
}
- インスタンスを生成し、print で値を取得する。
Test instanceTest = Test();
print(instanceTest.name);
しかし、name
にstatic
修飾子を追加すると、次のように直接クラスからアクセス出来る。
- class
class Test {
static String name = '田中さん';
}
- static があるため、インスタンスを生成せずに直接アクセスが出来ている、
print(Test.name);
これにより、クラスのインスタンスを生成することなく、クラス自体から変数やメソッドにアクセスできる。
使い分け
static
を使った方がいい画面:変数が持つ状態(値)が変わらない場合に使うのが良い。
static
を使わない方がいい場面:変数が持つ状態(値)が異なる時に使うのが良い。
要するに、
変数の値が変わる場合はインスタンスを作成する必要がある。
変わらない場合は、わざわざインスタンスを作成する必要がないため、static を使った方が良い。
■ 制御フロー
if文
- 構文
if (条件式) {
処理
}
- 例
void main() {
String texttest = '赤';
if (texttest == '赤') {
print('色は赤です');
}
}
三項演算子を使った条件分岐
- 構文
if (条件式) {
処理
} else {
上記のifがfalseだった時の処理
}
条件式 ? trueだった場合の処理 : falseだった場合の処理 ;
- 例
void main() {
String texttest = '白';
if (texttest == '赤') {
print('色は赤です');
} else {
print('色は赤ではありませんでした');
}
texttest == '赤' ? print('色は赤です') : print('色は赤ではありませんでした');
}
else if
- 構文
if (条件式) {
処理
} else if (条件式) {
上記のifでflaseだった場合の処理
}
- 例
void main() {
String texttest = '青';
if (texttest == '赤') {
print('色は赤です');
} else if (texttest == '青') {
print('色は赤ではなく青です');
}
}
else
- 構文
if (条件式) {
処理
} else {
上記のifがfalseだった時の処理
}
- 例
void main() {
String texttest = '白';
if (texttest == '赤') {
print('色は赤です');
} else {
print('色は赤ではありませんでした');
}
}
switch
複数のケースに対応した場合に使えるのかな。
- 構文
switch (式) {
case 値1:
// 値1に対応する処理
break; // これで1つの処理が終了する
case 値2:
// 値2に対応する処理
break; // これで1つの処理が終了する
case 値3:
// 値3に対応する処理
break; // これで1つの処理が終了する
default:
// どのケースにも一致しない場合の処理
}
- 例
void main() {
String colortest = '白';
switch(colortest) {
case '青':
print('青です');
break;
case '赤':
print('赤です');
break;
case '白':
print('白です');
break;
}
}
■ 演算子
算術演算子
演算子 | 意味 |
---|---|
+ | 足し算 |
- | 引き算 |
* | 掛け算 |
/ | 割り算(double型) |
~/ | 割り算(int型) |
% | 余り |
++ | 値を1増やす |
__ | 値を1増減らす |
代入演算子
演算子 | 意味 |
---|---|
a += b | a = a + b |
a -= b | a = a - b |
a *= b | a = a * b |
a /= b | a = a / b |
a ~/= b | a = a ~/ b |
比較演算子
演算子 | 意味 |
---|---|
a == b | a と b が同じという意味 |
a != b | a と b が異なるという意味 |
a > b | a が b より大きい |
a < b | a が b より小さい |
a >= b | a が b 以上 |
a <= b | a が b 以下 |
論理演算子
演算子 | 意味 | 役割 |
---|---|---|
! | 否定する場合に使う | 否定 |
|| | “又は” を意味する。”かつ”呼ぶ。 | OR 論理和 |
&& | 両方が成立する場合に使う | AND 論理積 |
型テスト演算子
演算子 | 意味 |
---|---|
is | 指定した型をもつ |
is! | 指定した型をもたない |
割り当て演算子
演算子 | 意味 |
---|---|
a ?? = b | a が null の場合にのみ、b を a に代入する。そうでなければ a はそのまま。 |
a ?? b | a が null でなければ a を、null であれば b を返す。 |
条件式演算子
演算子 | 意味 |
---|---|
x ? a : b | 条件 x が true なら a を 、false なら b を返す。 |
■ 非同期処理
Dart では非同期処理を実装する際、async/await を使う。
async
async は関数やメソッドの前に付けられる修飾子。
これを使うことで、その関数内で非同期処理を行うことができるようになる。
await
await は非同期関数内で使用でき、非同期処理の結果を待つ為に使用する。
これを使うことで、非同期処理が完了するまで次のプログラムの実行を待機し、順番に結果を取得できる。
■ その他
プライベート変数について
プライベート変数とは、他のクラスやページからアクセス出来ない変数の事を言う。スコープ(範囲)が限定されている。
プライベート変数にする為には、変数名の前にアンダーバー ( _ ) を追加するだけでいい。
(例)
- 通常の場合
class Test {
String name;
int age;
}
- プライベート変数を使った場合
class Test {
String name;
int _age;
}
Null Safety
Null Safety は Dart 2.12 以降から導入され、変数が null を許容するかどうかを明示的に示す機能。
null を許容する場合、型の後ろに ?
を使用します。
void main() {
int? nullTest = null; // null を許容する変数
int notNullTest = 42; // null を許容しない変数
print(nullTest); // nullと表示される
print(notNullTest); // 42と表示される
}
■ まとめ
難しい・・・
きっと色々な箇所で、微妙な言い方?理解?説明の部分もあるんだろうな。と思いながらまとめました。
これから Flutter をゴリゴリ書いていけば絶対に「ここはこういう説明の方が適しているな」とか「そもそもここの説明違ったや」ってなると思うので、気づき次第ブラッシュアップしていこうと思いました。
でも、なぁなぁでやるより1回こうやって形にしてまとめられたのは良かったと思う事にします。