したがって、拡張メソッドと拡張プロパティが実際には静的メソッドとプロパティです。また、静的メソッドとプロパティとメソッドはスレッドセーフではないため、避けるべきです。次に、拡張メソッドと拡張プロパティが悪いです。拡張メソッドと拡張プロパティは悪い習慣ですか?
私たちが書いたコードは、きれいだとは言えないが、パフォーマンスはそれほど高くないので、私たちはそれをするのはちょっと手抜きです。
これは本当ですか?
したがって、拡張メソッドと拡張プロパティが実際には静的メソッドとプロパティです。また、静的メソッドとプロパティとメソッドはスレッドセーフではないため、避けるべきです。次に、拡張メソッドと拡張プロパティが悪いです。拡張メソッドと拡張プロパティは悪い習慣ですか?
私たちが書いたコードは、きれいだとは言えないが、パフォーマンスはそれほど高くないので、私たちはそれをするのはちょっと手抜きです。
これは本当ですか?
拡張機能/プロパティの書き方によって異なります。それらが共有状態を編集またはアクセスしない場合、すなわちプロパティおよび機能が明確な機能である場合、それは絶対に悪いことではありません。
例1:String
は不変であるので、
fun String.countSpaces(): Int {
return this.count { c -> c == ' ' }
}
この機能は、マルチスレッド環境で完璧に動作します。
例2:
data class MutablePerson(val name: String, var speech: String)
fun MutablePerson.count(nextNumber: Int) {
this.speech = "${this.speech} ${nextNumber}"
}
この関数はMutablePerson
オブジェクトのspeech
プロパティを変異すると、操作がアトミックではない割り当てます。異なるスレッドから1つのオブジェクトに対してcount
が呼び出されると、不整合な状態が発生する可能性があります。
例:
fun main(args: Array<String>) {
val person = MutablePerson("Ruslan", "I'm starting count from 0 to 10:")
(1..10).forEach { it ->
Thread({
person.count(it)
println(person.speech)
}).start()
}
Thread.sleep(1000)
println(person.speech)
}
可能な出力:
I'm starting count from 0 to 10: 1
I'm starting count from 0 to 10: 1 3
I'm starting count from 0 to 10: 1 3 4
I'm starting count from 0 to 10: 1 3 4 2
I'm starting count from 0 to 10: 1 3 4 2 5
I'm starting count from 0 to 10: 1 3 4 2 5 8
I'm starting count from 0 to 10: 1 3 4 2 5 6
I'm starting count from 0 to 10: 1 3 4 2 5 6 7
I'm starting count from 0 to 10: 1 3 4 2 5 6 7 9
I'm starting count from 0 to 10: 1 3 4 2 5 6 7 9 10
I'm starting count from 0 to 10: 1 3 4 2 5 6 7 9 10
だから、拡張機能と拡張プロパティではない悪い習慣、彼らはただのクラスのプロパティとメソッドのようなものです:あなたは、彼らがスレッドに書いた方法に応じて、安全かどうか。
スタティックメソッドはインスタンスメソッドと同じように独自のスタックを持ちます。したがって、静的メソッド内の一時的な変数は、インスタンスメソッドと同様にスタックにあります。静的メソッドに渡されるパラメータは、共有状態にアクセスする際にスレッドの問題が発生する可能性がありますが、これはインスタンスメソッドとまったく同じ状況です。
Javaに拡張機能がないという回避策として、静的メソッドを使用したJavaのUtilクラスの膨大な量を考えてください。マルチスレッドに関しては何も間違っていません。 C#の拡張メソッドでも
は、シーンの静的メソッドの背後にある、それは、拡張機能を静的に解決され、あなたが言ったようにHow extension methods are implemented internally
を参照してください、任意の害を行いません。ですから、あなたがユーティリティクラスを作成する方法として拡張関数を使い始めるなら、それは悪い習慣です。
Javaでは、Utilsクラスは通常、スレッドの安全性だけでなく、悪い設計のためのコードの匂いやテストが難しいため、悪い習慣です。
静的メソッドの主な問題は、(少なくともMockitoを使って)嘲笑することができないため、コードをテストできないということです。
しかし、あなたはそれがすべてでは悪い習慣はありませんその後、テストする必要がない小さな、孤立したタスクのための拡張機能を使用する場合(トースト、ログのヘルパーのような...)
いいえ、声明」静的メソッドはスレッドセーフではありません "とは真ではありません(また、どちらも偽ではありません)。 – Ilya