Dart言語仕様 Pick-up

Dart言語仕様 Pick-up

2013

A8e4760b4a4b9227a12bcd37476987fd?s=128

Tomochika Hara

July 27, 2013
Tweet

Transcript

  1. 2.

    Agenda • Method Cascading • Named / Factory Constructor •

    Const Variable • Implicit Interfaces / Mix-in
  2. 4.

    • クエリ・コマンド分離原則に反する ◦ 状態を変えるメソッドなのに戻り値がある ◦ 戻り値がCalleeと同じ参照であることをシグネチャが表 現していない • 専用のシグネチャが必要 ◦

    ライブラリ提供者の意図を汲む必要がある ◦ 専用のシグネチャを持たないメソッドはMethod Chainで きない ◦ 変更に弱い ※ Method Chain != Fluent Interface 従来のMethod Chainへの批判
  3. 5.

    • 全てのメソッドをMethod Chainできる ◦ 戻り値を捨てる ◦ 代わりにMethod Cascading式で返される値がCalleeに なる ◦

    専用のシグネチャを定義する必要無し ◦ Method Chainするか否かはライブラリ利用者が自由に 決める • 使い道 ◦ DOM APIをjQuery-likeに ◦ 複数の副作用メソッドの呼び出しを一つの式に Method Cascadingでの解決
  4. 6.

    var tokai = (new StringBuffer("[") ..writeAll(["Aichi", "Gifu", "Mie"], ",") ..write("]")).toString();

    Method Cascadingの例 query("#sample_text_id") ..text = "Click me!" ..onClick.listen(reverseText); var person = (new PersonBuilder()..name = "to_hara"..age = 13).build();
  5. 8.

    Constructorの基本 class Person { final bool isAdult; Person(this.isAdult); } 仮引数の定義とフィールドの初期化

    class Person { final bool isAdult; Person(int age) : this.isAdult = age >= 20; } class Person { bool isAdult; Person(int age) : this.isAdult = age >= 20 { assert(age < 20 == !isAdult); } } フィールド初期化式リスト (コンストラクタのリダイレクト含む) オブジェクト初期化子 (finalフィールドへの初期化はできない)
  6. 10.

    • コンストラクタの実装をFactory Methodで ◦ クライアントからはGenerative / Factoryの違いはわか らない ◦ インスタンスのキャッシュ、パラメータから実クラスの選

    定、DIコンテナへの委譲など Factory Constructor abstract class Person { final int age; Person._internal(this.age); factory Person(int age) => age < 20 ? new Young(age) : new Adult(age); } class Young extends Person { Young(int age) : super._internal(age); } class Adult extends Person { Adult(int age) : super._internal(age); }
  7. 12.

    • コンパイル時にオブジェクト生成式を評価 ◦ 言語仕様によるFlyweightパターンの実装 ◦ 動作時の不変性が保証される • 用途 ◦ 不変性の明示?パフォーマンス?

    ◦ ぶっちゃけ用途がわからない・・・ ◦ finalではインライン展開されないことを厳密に既定し かった? ▪ Javaはプリミティブなfinal変数がインライン展開される。外部jar内のプ リミティブなfinal変数を参照、コンパイルした後、外部jar内のプリミティ ブなfinal変数の値を変えた場合、コンパイルしなおす必要がある 変数のインライン展開
  8. 13.

    • const初期化を可能にするコンストラクタ ◦ 要求(制限) ▪ 全てのフィールドにfinalがついていること ▪ 全てのフィールドの値がconst初期化できること ▪ オブジェクト初期化子が記述されていないこと

    ▪ Factory Constructor ではないこと Const Constructor class Location { final String name; const Location(this.name); } var l3 = const Location("Aichi"); var l4 = const Location("Aichi"); print( identical( l3, l4 ) ); // true
  9. 15.

    Implicit Interfaces (暗黙的Interface) • あらゆるクラスが暗黙的にインタフェースをもつ ◦ インタフェース=Java等と同じ ▪ 型名とメソッドのシグネチャのみが定義される class

    Person { final bool isAdult; Person(int age) : this.isAdult = age < 20; } class Young implements Person { // getterのオーバーライド bool get isAdult => false; }
  10. 16.

    Mix-in Application • クラスに振るまいを追加する ◦ 任意のクラスをMix-in可能にするための制限 ▪ コンストラクタが定義されていないこと ▪ Objectクラスを継承していること

    ▪ super呼び出しがされていないこと class Printable { void printMe() => print(this.toString()); } class Person extends Object with Printable { final int age; Person(this.age); String toString() => "I'm $age years old."; }
  11. 17.

    Implicit Interfaces & Mix - inの実用例 Dependency Injection : Cake

    Pattern class Repository { List<String> find() => ["data1", "data2"]; } class Service { Repository get repository => new Repository(); void execute() => print(repository.find()); } class AwesomeRepository implements Repository { List<String> find() => ["awesomeData1", "awesomeData2"]; } abstract class AwesomeRepositoryModule { Repository get repository => new AwesomeRepository(); } typedef AwesomeService = Service with AwesomeRepositoryModule;