Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Dart言語仕様 Pick-up

Dart言語仕様 Pick-up

2013

Tomochika Hara

July 27, 2013
Tweet

More Decks by Tomochika Hara

Other Decks in Technology

Transcript

  1. Dart言語仕様 Pick-up
    tomochikahara
    @zetta1985

    View Slide

  2. Agenda
    ● Method Cascading
    ● Named / Factory Constructor
    ● Const Variable
    ● Implicit Interfaces / Mix-in

    View Slide

  3. Method Cascading

    View Slide

  4. ● クエリ・コマンド分離原則に反する
    ○ 状態を変えるメソッドなのに戻り値がある
    ○ 戻り値がCalleeと同じ参照であることをシグネチャが表
    現していない
    ● 専用のシグネチャが必要
    ○ ライブラリ提供者の意図を汲む必要がある
    ○ 専用のシグネチャを持たないメソッドはMethod Chainで
    きない
    ○ 変更に弱い
    ※ Method Chain != Fluent Interface
    従来のMethod Chainへの批判

    View Slide

  5. ● 全てのメソッドをMethod Chainできる
    ○ 戻り値を捨てる
    ○ 代わりにMethod Cascading式で返される値がCalleeに
    なる
    ○ 専用のシグネチャを定義する必要無し
    ○ Method Chainするか否かはライブラリ利用者が自由に
    決める
    ● 使い道
    ○ DOM APIをjQuery-likeに
    ○ 複数の副作用メソッドの呼び出しを一つの式に
    Method Cascadingでの解決

    View Slide

  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();

    View Slide

  7. Named / Factory
    Constructor

    View Slide

  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フィールドへの初期化はできない)

    View Slide

  9. ● コンストラクタに任意の名前を付けられる
    ○ Dartは動的言語なので、パラメータの型によるコンストラ
    クタのオーバーロードができない
    ○ 複数のコンストラクタを定義するときは名前を付ける
    Named Constructor
    (名前付きコンストラクタ)
    class Person {
    final String name;
    Person(this.name);
    Person.copy(Person original) : this.name = original.name;
    }
    var hara = new Person("Hara");
    var hara2 = new Person.copy(hara);

    View Slide

  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); }

    View Slide

  11. Const Variable

    View Slide

  12. ● コンパイル時にオブジェクト生成式を評価
    ○ 言語仕様によるFlyweightパターンの実装
    ○ 動作時の不変性が保証される
    ● 用途
    ○ 不変性の明示?パフォーマンス?
    ○ ぶっちゃけ用途がわからない・・・
    ○ finalではインライン展開されないことを厳密に既定し
    かった?
    ■ Javaはプリミティブなfinal変数がインライン展開される。外部jar内のプ
    リミティブなfinal変数を参照、コンパイルした後、外部jar内のプリミティ
    ブなfinal変数の値を変えた場合、コンパイルしなおす必要がある
    変数のインライン展開

    View Slide

  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

    View Slide

  14. Implicit Interfaces
    / Mix-in

    View Slide

  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;
    }

    View Slide

  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.";
    }

    View Slide

  17. Implicit Interfaces & Mix - inの実用例
    Dependency Injection : Cake Pattern
    class Repository {
    List find() => ["data1", "data2"];
    }
    class Service {
    Repository get repository => new Repository();
    void execute() => print(repository.find());
    }
    class AwesomeRepository implements Repository {
    List find() => ["awesomeData1", "awesomeData2"];
    }
    abstract class AwesomeRepositoryModule {
    Repository get repository => new AwesomeRepository();
    }
    typedef AwesomeService = Service with AwesomeRepositoryModule;

    View Slide