1

シンプルストリーム(FRP)を実装するTypescriptでクラスを作成しました。今私はクライアント側の機能(イベントのストリーム)でそれを拡張したいと思います。私の問題を説明するために、ここにいくつかの疑似コードがあります:Typescriptでこのオブジェクトデザインを改善するにはどうすればよいですか?

class Stream<T> { 

    map<U>(f: (value: T) => U): Stream<U> { 
     // Creates a new Stream instance that maps the values. 
    } 

    // Quite a few other functions that return new instances. 

} 

このクラスは、サーバーとクライアントの両方で使用できます。クライアント側では、私はこの1つを拡張するクラスを作成しました:

class ClientStream<T> extends Stream<T> { 

    watch(events: string, selector: string): Stream<Event> { 
     // Creates a new ClientStream instance 
    } 

} 

ClientStreamクラス約mapを知っているがStreamクラス約watchを知りません。これを回避するために、関数はファクトリメソッドを呼び出します。

protected create<U>(.....): Stream<U> { 
    return new Stream<U>(.....) 
} 

ClientStreamクラスはClientStreamインスタンスを返すために、この機能を無効にします。ただし、コンパイラは、ClientStream.mapClientStreamではなく、Streamを返すと不平を言います。それは、キャストを使用して '解決'することができますが、醜いことに加えて連鎖を防止します。この問題を呈する

例コード:

class Stream { 

    protected create(): Stream { 
     return new Stream() 
    } 

    map() { 
     return this.create() 
    } 

} 

class ClientStream extends Stream { 

    protected create(): ClientStream { 
     return new ClientStream() 
    } 

    watch() { 
     return this.create() 
    } 

} 

let s = new ClientStream().map().watch() 

コンパイラによると、ストリームはmapから返されるので、これはコンパイルされませんがClientStreamではありません。error TS2339: Property 'watch' does not exist on type 'Stream'.

私は本当にこのようにしないでくださいパターンはありますが、私はよりエレガントなソリューションはありません。私が考えたこと:

  • 使用組成(デコレータ)。私がプロキシを通過させなければならないメソッドの数を考えると、実際にはオプションではありません。 ClientStreamについて心配することなく、後でStreamにメソッドを追加できるようにしたいと思います。
  • StreamClientStreamにミックスします。多かれ少なかれ同じ問題があり、ClientStreamは混在しようとしている関数のシグネチャを知っていなければなりませんか?教えてください。
  • これらのクラスを1つに統合します。これは最後の手段であり、watchの機能はサーバー上に存在しません。

優れた(よりエレガントな)ソリューションがありますか?より機能的なスタイルに近づくアイデアがあるなら、それについて聞いて嬉しいです。ありがとう!

+0

ファクトリメソッドは静的にできますか?あるいは、インスタンスデータに依存していますか? –

+0

はい、静的である可能性があります。 –

+0

@SebastianSebaldが述べたように、 '多型この型'を使うことができますが、あなたのクラスは一般的なので難しくなります。私はまだあなたの問題を理解しようとしています。おそらく、問題を示す完全な例でコードを更新できますか?私はちょうど遊び場に貼り付けることができ、エラーが何で、どこにあるか見ることができます。 –

答えて

0

あなたがしようとしているのはF-bounded polymorphismです。

TypeScriptでは、これはthisキーワードで行われます。 polymorphic this typesのTypescriptのドキュメントを見てください。あなたがドキュメントに従うなら、あなたが望むものを実装できるはずです:-)

実際には、あなたのメンバーメソッドでthisを返すようにしてください。

+0

提案していただきありがとうございます。私は間違っている可能性がありますが、これは建築家のパターンだけではありませんか?ここには変更可能な状態がありますが、私はこれを防止したいと思います。余分な '.currentValue()'コール(ビルダーの典型)の場合も同じです。 –

+0

これがビルダーパターンであるかわかりません。私はウィキペディアでそれを見て、あまりにも私は、それはビルダーのパターンが何かを持っているようだwieクラスの継承。私が間違っているなら、私を訂正してください。あなたは可変状態をどこに見ますか? –

+0

typescriptサイトの電卓の例では、計算ごとに 'this.value'が変更されています。 –

関連する問題