今回はDartというプログラミング言語のドキュメント(https://dart.dev/guides/language/language-tour)を読んで、実際に動かしてみよう、というテーマでお話したいと思います。
まずそもそも、Dartとは何か?ということについて、ざっくりとご紹介いたします。
Dartとは、Googleによって開発されたプログラミング言語で、Webアプリケーションやスマートフォンのアプリ開発で用いられています。Flutterという言葉を聞いたことのある方も多いのではないでしょうか?
DartはFlutterでアプリケーション開発を行う際に用いられる言語で、FlutterではDartを各環境に合わせてbuildすることでさまざまなアプリケーションをDartで開発できるという仕組みです。
決して短い内容ではないので、何回かに分けてご紹介できればと思います。
今回は基本事項から、変数についてまでをご紹介いたします。また、内容はある程度他の言語の知識が必要な部分もありますがご了承ください。。。
・Dartのドキュメント(https://dart.dev/guides/language/language-tour)
–> 内容はこのページに沿っています。
・Dart Pad(https://dartpad.dev/) –> Dartのコードを試せるplaygroundです。コードをすぐに試せます。
なにはともあれ、Dart Padを開いてチュートリアルにある下記のコードを実行してみましょう。
// Define a function.
void printInteger(int aNumber) {
print('The number is $aNumber.'); // Print to console.
}
// This is where the app starts executing.
void main() {
var number = 42; // Declare and initialize a variable.
printInteger(number); // Call a function.
}
以下のように表示されました。では、簡単に基本的な事項を見ていきます。
void main(){ … }という部分があります。
Dartではmainという関数から実行されるというルールがあります。この関数はmain()のように記述しなくても実行されます。
そして、voidとある部分が関数の戻り値(返り値)の型です。他の言語と同様に、voidは値を返さないことを示します。
main関数から実行されることが分かりましたので、処理を順に追っていくことにします。
まずは、var number = 42とあります。Dartではvarの場合型の推論が行われます。このとき、初期値によって推論されるのですが、この場合は「42」が初期値ですので、int型と推論され、変数numberはint型になります。
次にprintIntegerですが、これは関数で、main関数の外に宣言があります。
void printInteger(int aNumber)とありますので、この関数は値を返さないことが分かります。引数はint aNumberですので、int型ですね。
処理内容はprint(‘The number is $aNumber.’)ですが、ここでprint関数は引数の値を出力する関数です。
引数は‘The number is $aNumber.’とあります。ここで$aNumberの部分ですが、Dartではこのように記述することで、変数や式の中身を文字列に埋め込むことができます。
以上で、画像のように出力されたことが理解できました。
Dartはv2.12以降、null safetyな言語です。
従って、Dartではそのことを明示しない限りnullを代入することはできません。
?をつけることによってnullを許容することが可能になります。例えば、次のコードはエラーになります。
void main() {
int hoge = null;
print(hoge);
}
しかし、次のコードはエラーになりません。
void main() {
int? hoge = null; // int を int? に変更
print(hoge);
}
また、変数にnullが許容されている場合であっても、値がnullでないことが保証されている場合、!によってアンラップする(nullでないことを明示する)ことができます。
※この場合、null-safetyを強制的に無視することになりますので、注意が必要です。
Dartでは、Javaなどにあるようなprivate、protectedといったキーワードは存在しません。
しかし、_hogehogeのように、識別子が_から始まる場合、そのライブラリ内でプライベートとなります。
次は変数について見ていきます。
既に出てきたvarでは型推論が行われるのでしたが、明示することも可能です。その場合は次のように宣言します。
String company = 'レッカスグルーヴ';
Object name = 'ほげほげ';
明示的に初期化されない変数はnullで初期化されるため、nullを許容しない変数では次のようなコードはエラーとなります。
このような場合、変数を使用する前に正しい値を代入する必要があります。
※ 多くの場合はこれで大丈夫ですが、特別なケースとしてlate修飾子が必要になる場合があります。(後述)
void main() {
int name;
print(name);
}
Dart2.12からlate修飾子が追加されました。
これは、「変数を使用する前に正しい値が代入されることが保証されているが、Dartが同意せずエラーとなる」ケースで使用できます。
例えば、以下のケースはエラーとなります。
※ 前述の通り、多くの場合はDartは変数使用前に値が代入されることを判定し、エラーを出しません。
String description;
void main() {
description = 'Feijoada!';
print(description);
}
この場合は以下のように修正します。
もし、lateとなっている変数が初期化に失敗した場合、実行時にエラーが発生します。(コンパイルエラーにはなりません)
late String description; // late 修飾子を追加
void main() {
description = 'Feijoada!';
print(description);
}
最後にfinalとconstについてご紹介します。これらはどちらも再代入不可の定数を表すものですが、それぞれ違いがあります。
まず、finalを使用してみます。実行時の日時が出力されます。
void main() {
final nowFinal = DateTime.now();
print(nowFinal);
}
再代入不可なので、次のようにするとエラーとなります。
void main() {
final nowFinal = DateTime.now();
nowFinal = DateTime(2022, 11, 10); // 2022.11.10 を再代入しようとしてみる
print(nowFinal);
}
では、次にconstを使用してみます。
次のコードはエラーとなります。
void main() {
const nowFinal = DateTime.now();
print(nowFinal);
}
再代入していないにもかかわらず、なぜエラーになったかというと、constが「コンパイル時定数」であるということが理由です。
一方、finalは「実行時定数」です。
DateTime.now()は実行時に評価(コンパイル後に変更)されますので、constとするとエラーになったということです。
(コンパイル後に変化する値でない値に対して使用しますので、例えば、クラスの宣言でstatic const hoge = “fuga”;のように用います。)
いかがでしたでしょうか。ドキュメントから少し端折ってしまった部分もありますので、Flutterでスマートフォンアプリを開発してみたい!といった方などは、是非一度ドキュメントにも目を通されるのが良いかと思います。
次回の私の記事では「型」と「関数」についてご紹介したいと思いますので、引き続きよろしくお願いいたします。
山口県生まれ、山口県育ち。超インドアなので外出することは少なめですが、Webを身近に感じていただける技術トピックなどを中心にご紹介できればと思っています。よろしくお願いいたします!
REC.