2016-06-22 4 views
2

私はkotlin初心者ですので多分これは簡単ですが、kotlinlang.orgで関連するヘルプを見つけることができませんでした。SAMインターフェイスを返す関数のオブジェクト式を避けるにはどうすればいいですか

kotlinについて少し学ぶために、私はPushStreamライブラリを実装したいと思います。

typealias Receiver<T> = (T) -> bool 
typealias PushStream<T> = (Receiver<T>) -> Unit 

私の知る限りの型の別名はまだので、上記のサポートだけで擬似コードでされていません。

は、私はこのような基本的なタイプのものを定義したかったです。

interface Receiver<T> : (T) -> Boolean { 
} 

interface PushStream<T> : (Receiver<T>) -> Unit { 
} 

fun <T> singleton (v : T) : PushStream<T> { 
    return { r : Receiver<T> -> r (v) } 
} 

kotlinはその後、言う:

Error:(10, 12) Kotlin: Type mismatch: inferred type is (Receiver<T>) -> Boolean but PushStream<T> was expected 

は、私はそれを回避することができるように見える:

fun <T> singleton (v : T) : (Receiver<T>) -> Unit { 
    return { r : Receiver<T> -> r (v) } 
} 

しかし、それはありません

だから私の最初の試みは、このました私が特に高度な演算子のために必要とする署名私は完全な関数型を指定する必要があるかもしれない:

fun <T> singleton (v : T) : ((T) -> Boolean) -> Unit { 
    return { r : Receiver<T> -> r (v) } 
} 

これは私がAPIを読みにくくすると考えています。

fun <T> singleton (v : T) : PushStream<T> { 
    return object : PushStream<T> { 
     operator override fun invoke (r : Receiver<T>) : Unit { 
      r (v) 
     } 
    } 
} 

これは動作しますが、私はより簡潔コードを維持するためにラムダ式を使用したい:私は何ができるか

は、オブジェクト式を使用しています。

ヒントをお聞かせください。また、興味のあるブログ/プレゼンテーションを知っていれば、コトリンの高次関数を使ったプログラミングについても、大いに感謝しています。

+2

Kotlinは暗黙のSAMのインタフェース変換をサポートするための選択をしましたJavaインタフェースのみの機能Kotlinインターフェース用ではありません。私はこれがいくつかのケースで可読性を傷つけることに同意します。タイプエイリアスは次のバージョン(AFAIR)に追加されます。 JetBrainsは、Kotlinインターフェイスの変換が許可されるべきかどうかの問題を修正するかどうかを確認します。 https://youtrack.jetbrains.com/issue/KT-7770の機能リクエストがあります。その間、私は '(T) - > Boolean'を署名に使用します。うまくいけば、タイプエイリアスでコードをリファクタリングすることはあまり難しくありません。 –

答えて

2

型のエイリアスが(まだ)存在しないため、型シグニチャは互いに代用できません。あなたのケースでは、抽象化のレベルを作成するために、組成物の代わりに、継承を使用する必要があります。

open class Receiver<T>(val op: (T) -> Boolean) 

open class PushStream<T>(val op: (Receiver<T>) -> Unit) 

fun <T> singleton (v: T): PushStream<T> { 
    return PushStream<T> { r -> r.op(v) } 
} 

私は、コードの残りの部分を見ていないので、私はクラスとインタフェースを置き換えます。あなたはインターフェースが必要な場合は、ファクトリ関数を使用します。

interface Receiver<T> { 
    val op: (T) -> Boolean 
} 

fun <T> receiver(op: (T) -> Boolean) = object : Receiver<T> { 
    override val op = op 
} 
+1

アイデアありがとう。 – FuleSnabel

1

あなたはJavaでPushStream-インタフェースを定義した場合、あなたはそのようにそれを使用することができます:

fun <T> singleton (v : T) : PushStream<T> { 
    return PushStream { r : Receiver<T> -> r (v) } 
} 
関連する問題