Dartの静的型付け
と、見出しで銘打っておいてなんですが、Dartは動的な型付けを行っています。
これは、「多くの開発者に支持されているJavaScriptの性質を維持する」というDartのコンセプトで考えれば、自然な事だと言えます。
とはいえ、動的な片付けはJavaScriptが大規模な開発に向かない一因でもあるため、Dartでは静的型付けによるプログラミングが「いちおう」サポートされています。
「いちおう」というのは、Dartにおいて「型エラー」は「エラー」にはならず、「警告」として処理されるからです。
例えば、
main() { String foo = "5"; int bar = 3; bar += foo; //Warning:String is not assignable to num print(bar); }
この例では、「bar += foo」の箇所でWarningが表示され、「35」が出力されます。
また、
main() { String foo = "5"; int bar = 3; foo += bar; print(foo); //「53」と表示 }
先程のコードのfooとbarを入れ替えただけですが、この例では警告すら表示されません。これは、「foo += bar」が文字列の連結として評価され、文字列変数であるfooに代入されるため、構文上問題が無いからです。
実行できるからといって、次のような書き方をするのは危険です。
main() { int foo = "10"; //ここで警告 int bar = 5; print(foo+bar); }
この例では、int型の変数同士を加算しているのにも関わらず、変数fooの値は文字列の「10」を保持しているため、出力は「105」となります。
次のコードはエラーも警告も出ません。
class Foo{ var bar = "Hello!"; } main() { var myVar = new Foo(); print(myVar.bar); }
次のようにすれば、Objectクラスはbarというメンバを持っていないため、警告が表示されます。(実行する事は可能です。)
class Foo{ var bar = "Hello!"; } main() { Object myObj = new Foo(); print(myObj.bar); }
次の例は、警告が表示されますが、実行可能で、「Hello,Baz!」が表示されます。
class Foo{ var bar = "Hello,Foo!"; } class Baz{ var bar = "Hello,Baz!"; } main() { Foo myFoo = new Baz(); print(myFoo.bar); }
継承関係にあれば暗黙のうちに型変換が行われるため、次の例では警告は表示されません。
class Foo{ var bar = "Hello!"; } main() { Object myObj = new Foo(); Foo myFoo = myObj; //Dartにキャッシュの構文はない print(myFoo.bar); }
class Foo{ var bar = "Hello,Foo!"; } class Baz extends Foo{ var qux = "Hello,Baz!"; } main() { Foo myFoo = new Baz(); Baz myBaz = myFoo; print(myBaz.qux); }
以上、Dartの静的型付けについてざっと例を並べてみましたが、どうでしょうか。
型について厳密に定義されている言語に慣れいている人にとっては、すこし柔軟すぎて、不安を感じさせる仕組みかもしれません。
JavaScript等に慣れている人にはDartの任意的な型付けは魅力的に感じるのでは無いでしょうか。
おそらく大規模開発では、クラスや関数の内部で小規模に使われる変数には動的な型付けを、それ以外の、広く使われる関数やメソッドの戻り値、プロパティ等には静的な片付を行うようになっていくのでは無いでしょうか。
エラーが発生しないとは言え、やはり型の整合性が取れないのは危険ですから、Warningを残しておくような事はすべきでないでしょう。
それらを踏まえてた上で、
JavaScriptの欠点を補うという意味では、Dartの静的型付けは十分な要件を満たしているのでは無いかと思います。