2017-10-06 5 views
1

私はKotlin抽象クラスの拡張とジェネリックについて、組み込みクラスを拡張する非常に簡単なメソッドとプロパティゲッターを構築することで、もっと学びたいと考えています。私はほとんど成功しましたが、私はNumberクラスに困惑しています。私のテストプロパティNumber.sgnは、Numberの任意のサブクラスの符号(1または-1をIntとして返します)を返します。簡単にするために、ネガティブは-1を返すべきですが、正の数と0は1を返さなければなりません。私はこのメソッドのユースケースに特に興味はありませんが、このような単純なものを書く方法を理解するため、エラーがあります。私のモジュールで唯一のインポートはkotlin.text.*であり、私が受け取るエラーメッセージには競合が参照されています。私はそれが矛盾する理由とそれを克服する方法を理解していません - 私はそれが初心者のエラーだと思っていますが。私はこのように、一般化およびNumberクラスに移動しようとしたすべてのNumberサブクラスで動作する単純なプロパティゲッターを作成するには、Kotlin Numberクラスを拡張するか、またはジェネリックを使用しますか?

inline val Int.sgn get() = if (this<0) -1 else 1 // sign of number

inline val Number.sgn get() = if (this<0) -1 else 1 // doesn't compile

は、私が最初に正常に動作のIntクラスを拡張するためのコードを書きました

であり、コンパイルエラーは次のとおりです。

unresolved reference. None of the following candidates is applicable because of receiver type mismatch: public fun String.compareTo(other: String, ignoreCase: Boolean = ...): Int defined in kotlin.text inline fun Number.sgn() = if (this<0) -1 else 1 ^

私は、ジェネリックを使用して、別のアプローチを試してみました:

inline val <T:Number> T.sgn get() = if (this<0) -1 else 1

を、私は、コンパイラから同じエラーを受信:

error: unresolved reference. None of the following candidates is applicable because of receiver type mismatch: public fun String.compareTo(other: String, ignoreCase: Boolean = ...): Int defined in kotlin.text inline val <T:Number> T.sgn get() = if (this<0) -1 else 1 ^

誰が、なぜ私が理解するのに役立つだろうタイプの不一致、なぜkotlin.textがここで重要なのでしょうか?この問題を克服し、このプロパティゲッターをNumberのすべてのサブクラスに適用するために使用できるアプローチはありますか? (これは意味のあるユースケースではなく、この背後にある原則を理解するのに役立つ簡単な例です)。

答えて

1

最初の機能は次の理由で機能します。 IntComparable<Int>を実装しています。それは<オペレータが翻訳したものです。しかし、Numberクラスを見ると、さまざまなサブクラスに変換するための関数しかないことがわかります。Comparableを実装していないため、<演算子は使用できません。

あなたNumber最初Doubleに変換し、それが負だかどうかを確認している代わりに、何ができるか:実装することで、作業を(またはジェネリックなしのいずれか)

inline val <T : Number> T.sgn 
    get() = if (this.toDouble() < 0) -1 else 1 

あなたはまた、あなたの元のコードを作ることができます拡張機能としてNumberためcompareTo機能:

operator fun Number.compareTo(other: Number) = this.toDouble().compareTo(other.toDouble()) 

ちょうどDoubleにすべてをキャストすると、精度を失うことになるかもしれないことに注意してください。

+0

迅速/徹底的な答えをありがとう。私がcompareToの道を始めると、NumberのcompareToの実装を探すのではなく、問題の特定のNumberクラスのcompareToを呼び出すようにKotlinを取得する方法を調べようとしました。 'inline val T.sgn T:Number、T:Comparable get()= if(this <(0 as T))-1 else 1'それは動作しますが、私は、Tを明らかにすることなくジェネリック医薬品を使用している可能性があるかどうか、そして/またはReplayがパフォーマンスに重大な影響を及ぼすかどうかを私は理解していません。再度、感謝します! – sirksel

関連する問題