はじめに
Pythonが初めてのプログラミング言語だった方向けにDartの文法についてまとめました.Pythonと違うところにだけ注目してまとめました.
flutter公式サンプルのカウンターアプリのコードが理解できるレベルを目標にしています.
間違い等ありましたら,遠慮なくコメントください!
**以降の説明ではシンプルに書くために、main
関数は省いてあります。**実際に動かすときにはmain
関数の中に記述する必要があります。また,型注釈があってもなくてもいいときは,型注釈をつける文法のみを紹介します.
main
関数
プログラムの中にmain
という名前の関数を1つ絶対に定義しなければならない。main
関数が一番最初に呼び出されてプログラムがスタートする.
型注釈
基本的に型注釈が必要.型注釈というのは変数や関数の戻り値の型をコード中に明記すること.動的型付けのPythonと違って,Dartは型注釈が必要な静的型付けである.一応動的型付けもサポートはされているが,静的型付けに従うのが吉.メリットは色々あるが一番しっくり来るのは,関数の中身のコードを読まなくても関数名と型注釈を確認するだけで,その関数がどの型に対してどんな変換を行なってどの型を返すのかという情報がひと目でわかるから.
**型注釈は関数や変数の定義時に,関数名や変数名の前に書く.**変数や関数の定義の仕方については後ほど説明するので,ここでは型注釈は定義時に名前の前に記述するということだけ把握しておいてください.
int variable;
int function(int variable0, int variable1){}
基本的なルール
行の末尾にセミコロンを書く必要がある。
print("hoge");
インデントではなく、{}
でまとまりを表す。中括弧のあとにセミコロンはいらない。
hoge(){
print("hoge");
}
型注釈
コメント
// coment
/*
hoge
hoge
hoge
*/
///document
///document
変数
定義と代入は別の作業であり、代入をする前にvar
を使って変数を定義する必要がある。
var hoge;
定義と代入を一行で書くこともできる。
var hoge = 0;
var
の代わりに、型を指定して定義することもできる。この場合はその変数にはその型のオブジェクトした代入できないようになる。
int hoge;
先頭にアンダースコアを一つつけるとprivate扱いになり、クラスの外からアクセスすることができなくなる。
int _hoge = 2;
定数
const
やfinal
を使うことで定数を定義できる。使い分けについて現在咀嚼中
参考になりそうなリンクだけ貼っておきます。
https://qiita.com/uehaj/items/7c07f019e05a743d1022#final%E6%8C%87%E5%AE%9A
https://stackoverflow.com/questions/50431055/what-is-the-difference-between-the-const-and-final-keywords-in-dart
そもそも定義時に使用するものなので、var
をつけなくてもOK。
final hoge;
もちろん型を指定することもできる。
const int hoge =0;
文字列への変数の埋め込み
ドルマーク$
の後に変数名を書くことで変数を文字列中に埋め込める。String型以外の場合には、自動的にString型に変換される。
var hoge = 0;
print("hoge refers $hoge");
純粋な変数ではないもの(フィールドとか)を埋め込みたいときは中括弧でくくる。
print("1 + 1 = ${1 + 1}");
型変換
int型からString型に変換するときは以下のようにする。文字列に埋め込むために変換したい場合は変数の埋め込みを使う。コンソールにprint
するときなど、String型以外のものを文字列で表したいことは多々あるので、toString
メソッドは大抵のオブジェクトに定義されている。
String oneAsString = 1.toString();
String型からint型に変換するときは以下のようにする。toStirng
メソッドと違ってparse
メソッドはint型特有のメソッドである。
var one = int.parse('1');
関数
def
のような、関数の定義の前置きはない。関数名の前に戻り値の型を宣言することができる。戻り値を返さないのはvoid
という型になる。
int hoge(int number){
return number;
}
関数の中のコードが一行しかない場合は、=>
という矢印のマークを使って見やすいコードが書ける。=> 式
と{ return 式; }
は同じ意味。
void main() => print("hoge");
名前付き引数
中括弧でくくった引数は、引数名を指定して引数を渡すことができるようになる。名前付き引数はオプション引数の部類に含まれることになるので、省略することもできる。省略した場合null
が返される。Pythonとは違って、名前付き引数でないと引数名を指定して渡すことはできない。
int hoge({int number}){
return number;
}
省略させたくないときは、@required
をつけて強制することもできる。ただし、このアノテーションを使うにはpackage:meta/meta.dart
をインポートする必要がある。
int hoge({@required int number}){
return number;
}
引数名を指定して関数を呼び出すときはコロン:
を使って引数を指定する。
hoge(name : "Mike");
演算子
メジャーな演算子のうち、PythonとDartで異なるものだけをまとめた。
Dart | Python |
---|---|
~/ | // |
++ | +=1 |
-- | -=1 |
&& | and |
|| | or |
??=
代入演算子の一つ。nullのときにだけ特定の処理をさせることはよくあるので、便利な演算子が用意されている。この演算子は、左辺ががnullのときだけ代入処理を行う。
int a;
a ??= 3;
aには最終的に3が代入される。
??
上の演算子と似ているが、こちらは値を返す。左側がnullのとき右側を返す。
int a;
print(a ?? 3)
3がコンソールに出力される。
制御文
条件は()
でくくる。
if
異なるのはこれだけ。
Dart | Python |
---|---|
else if |
elif |
if-elseの代替構文
条件によって返す値を変えたいということはよくある。そんなときのために便利な構文が用意されている。
bool値 ? 式 : 式
という形で使用する。bool値がTureのときコロンの左側の式を返し、Falseのとき右側を返す。なるべく式がシンプルな場合に使うと良いだろう。
var isPerson = true;
print(isPerson ? "Yes": "No");
この場合、Yesと出力される。
for
条件の部分は(変数定義と代入; 継続条件; 継続時処理)
というような書き方。
for (int number = 0; number < 3; number++){
print(number);
}
Pythonのコードと似ている書き方にも対応している。
var numbers = [0, 1, 2];
for (var number in numbers) {
print(number);
}
switch
あることにはあるが、Pythonでは使わずにやってきたのでとりあえず割愛。
import
Pythonでは、パッケージやモージュールの名前を指定するが、DartではURIを指定する。URIは識別子ではなく文字列なのでシングルクォーテーションやダブルクォーテーションでくくる。ちなみにURIというのはURLの進化形で、「URLで使われるhttpとかhttpsとかのスキーム以外も利用して、万物にURLみたいな名前を付けよう!」的な考えをもとに作られた表記方法。URIの構成はスキーム:パス
となっている。1パッケージを利用するときのスキームはpackage
、Dartの組み込みライブラリを利用するときはdart
。
単に別ファイルのdartファイルを読み込みたい場合は絶対パスか相対パスを入力する。
アノテーション
@
で始まる文はアノテーションと呼ばれ、メソッドなどに特定の性質を割り当てたりするのに利用される。Pythonでいうデコレータ的なもの。
クラス
クラス変数とインスタンス変数
クラス変数とインスタンス変数の違いは、static
をつけて修飾するかしないかということ。修飾した場合、クラス変数として扱われ、クラスに共通な変数として扱うことができる。定義する場所はクラス変数もインスタンス変数もclass直下。
Pythonのクラスについて理解が怪しい場合はこちらの拙著をどうぞ。
class JapanesePerson{
static String nationality = "Japan"; // クラス変数
int age; // インスタンス変数
String name; // インスタンス変数
}
this
Pythonのように、インスタンスをselfという引数としてメソッドに与えるという作業は必要ない。Dartではthisはメソッド内で使用する時、自分自身を返す特別な変数である。
class Person{
String name;
void info(){
print("My name is ${this.name}");
}
}
コンストラクタ
-
クラスと全く同じ名前
-
戻り値の型が指定されていない
-
戻り値がない
のすべてを満たしたメソッドがコンストラクタとして認識される。
class Person{
String name;
Person(name){
this.name = name;
}
}
以下コンストラクタのいろんな機能
Syntactic sugar(便利な構文)
コンストラクタの引数にインスタンス変数を渡すと自動的に代入処理が行われる。上のコードとやってることは全く同じ。
class Person {
String name;
Person(this.name);
}
名前付きコンストラクタ
DartやPythonではオーバーロード(同じ名前のコンストラクタを定義して、変数の数によって自動的に使い分けてくれる機能)がない。その代替策として、クラス名.任意名称()
とすることで複数のコンストラクタを作ることができる。インスタンス化するときも、クラス名.任意名称()
と言うようにして呼び出す。
class Person{
String name;
Person(name){
this.name = name;
}
Person.gest(){
this.name = "gest";
}
}
定数コンストラクター
インスタンスの持つフィールドの値が変化しないオブジェクトをインスタンス化したいときに使いう。すべてのフィールドを定数にして、コンストラクタの先頭にconst
をつける必要がある。
class Hoge{
final name;
const Hoge(this.name);
}
コンストラクタのリダイレクト
コロンの後に別のコンストラクタを記述することで、別のコンストラクタを呼び出して処理をバトンタッチすることができる。この場合のthisは自分自身、つまりPersonを返しているので、Personコンストラクタに"gest"
を渡していることになる。
class Person{
String name;
Person(name){
this.name = name;
}
Person.gest(): this("gest");
}
継承
Pythonでは親となるクラスは()
に記述するが、Dartではextends
のあとに記述する。
class Person{
int age;
String name;
}
class JapanesePerson extends Person{
static String nationality = "Japan";
}
super
super
は親クラスを返す。superの部分がクラス名に化けると考えてよいので、super()
とすると親クラスのコンストラクタを呼び出すことになる。
Pythonとの大きな違いはコンストラクタの中でsuper
は使えないという点。これを回避するためにコンストラクタのリダイレクトを使う。
親クラスのコンストラクタを呼び出すときはこんな感じ。コンストラクタのリダイレクトとSyntactic sugarを応用している。
class Person{
int age;
String name;
Person(this.age, this.name);
info (){
print("My name is ${this.name}.");
}
}
class JapanesePerson extends Person{
static String nationality = "Japan";
var prefecture;
JapanesePerson(age, name, this.prefecture): super(age, name);//ココ
}
オーバーライド
アノテーションとして@override
を上の行につける必要がある。
@override
info(){
print("hoge");
}
setter/getter
assert()
簡易的に関数のテストを行うために使う。ただしこの方法ではテストが失敗したときに,実際にはどんな値が返されたのか表示してくれないので実際にデバッグするときに手間がかかる.そのため,基本的にtestパッケージを使うのがおすすめ.assertは使い捨てのコードなど,テストのためのコードをきっちりとかくのが馬鹿らしいときに使う.
assert(n == 1);
参考にしたサイト
Dartのコンストラクタについて | Developers.IO
-
パスの部分なんですけど、httpの場合ってパスの先頭が
//
ってなってますよね?これはスキームがhttpの時だけのルールみたいです。 ↩