【问题标题】:Are extension methods and extension properties are bad practice?扩展方法和扩展属性是不好的做法吗?
【发布时间】:2016-11-14 21:29:33
【问题描述】:

所以如果扩展方法和扩展属性是真正的静态方法和属性。并且静态方法和属性和方法不是线程安全的,因此应该避免扩展方法和扩展属性是不好的。

我们只是被欺骗了,因为我们编写的代码看起来很漂亮或干净,但在性能方面却不是。

这是真的吗?

【问题讨论】:

  • 不,“静态方法不是线程安全的”语句不正确(也不是错误的)。
  • 如果它是关于线程安全的,那么整个面向对象将是糟糕的。除非没有可变状态,对象只能由构造函数构造,方法返回不可变对象的新实例。

标签: kotlin kotlin-extension


【解决方案1】:

这取决于您如何编写扩展函数/属性。如果他们不编辑或访问共享状态,即如果属性和功能是明确的功能:这绝对不是坏习惯。

示例 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属性并且赋值操作不是原子的。如果 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

所以扩展函数和扩展属性是不错的做法,它们就像类中的属性和方法:取决于你如何编写它们是否线程安全。

【讨论】:

    【解决方案2】:

    静态方法和实例方法一样有自己的堆栈。因此,静态方法中的临时变量就像实例方法一样在堆栈上。传递给静态方法的参数在访问共享状态时可能会遇到线程问题,但这与实例方法完全相同。

    将 Java 中大量的带有静态方法的 Util 类视为 Java 没有扩展函数的一种解决方法。多线程方面没有任何问题。

    在 C# 中,扩展方法也是静态方法,它不会造成任何伤害,请参阅 How extension methods are implemented internally

    【讨论】:

      【解决方案3】:

      正如您所说,扩展函数是静态解决的。因此,如果您开始使用扩展函数作为制作实用程序类的一种方式,那么这是一种不好的做法。

      在 Java 中,Utils 类通常是一种不好的做法,这不仅是因为线程安全,还因为它们可能会成为不良设计的代码味道,并且难以测试。

      静态方法的主要问题是它们不能被模拟(至少使用 Mockito),所以你将无法测试你的代码。

      但是,如果您将扩展函数用于不需要测试的小型、孤立的任务,那么这根本不是一个坏习惯(例如 Toasts、Logs 的助手......)

      【讨论】:

      • 小型、孤立的任务,无需测试 - 出类拔萃!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-09-06
      • 1970-01-01
      • 1970-01-01
      • 2023-03-16
      • 1970-01-01
      • 2010-11-20
      • 1970-01-01
      相关资源
      最近更新 更多