Являются ли методы расширения и свойства расширения плохой практикой?

Поэтому, если методы расширения и свойства расширения являются действительно статическими методами и свойствами. Статические методы и свойства и методы не являются потокобезопасными, поэтому их следует избегать, поэтому методы расширения и свойства расширения плохие.

Мы просто обманываем их, потому что коды, которые мы пишем, будут казаться красивыми или чистыми, но с точки зрения производительности это не так.

Это правда?

Это зависит от того, как вы написали функцию / свойство extension. Если они не редактируют или не получают доступ к общему состоянию, т. Е. Если свойство и функция являются ясной функцией: это абсолютно неплохая практика.

Пример 1:

fun String.countSpaces(): Int { return this.count { c -> c == ' ' } } 

Эти функции отлично работают в многопоточной среде, поскольку String неизменен.

Пример 2:

 data class MutablePerson(val name: String, var speech: String) fun MutablePerson.count(nextNumber: Int) { this.speech = "${this.speech} ${nextNumber}" } 

Эта функция MutablePerson свойство speech объекта MutablePerson и назначение операции не является атомарным. Если 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 

Таким образом, функции расширения и расширения не имеют плохой практики, они похожи на свойства и методы в классах: в зависимости от того, как вы написали, они потокобезопасны или нет.

Статические методы имеют свой собственный стек как метод экземпляра. Таким образом, временные vars внутри статических методов находятся в стеке точно так же, как, например, методы. параметры, которые передаются статическому методу, могут быть связаны с проблемами потоковой передачи при доступе к общему состоянию, но это точно такая же ситуация с методами экземпляра.

Подумайте о огромном количестве классов Util в Java со статическими методами в качестве обходного пути, что Java не имеет функций расширения. В отношении многопоточности ничего не случилось.

Также в методах расширения C # находятся за статическими методами сцены, и это не наносит вреда, см. Как внутренние методы реализации реализованы внутри

Как вы сказали, функции расширения решаются статически. Поэтому, если вы начнете использовать функции расширения как способ сделать классы Утилиты, тогда это плохая практика.

В Java класс Utils обычно является плохой практикой не только из-за безопасности потоков, но и потому, что они могут быть запахом кода для плохого дизайна и потому что их трудно тестировать.

Основная проблема со статическими методами заключается в том, что их нельзя издеваться (с Mockito, по крайней мере), поэтому вы не сможете проверить свой код.

Но если вы используете функции расширения для небольших изолированных задач, которые не нуждаются в тестировании, то это совсем не плохая практика (например, помощник для тостов, журналов …)