Kotlin 扩展函数与成员函数?
Kotlin extension functions vs member functions?
我知道 Kotlin 中使用扩展函数来扩展 class 的功能(例如,来自库或 API 的功能)。
但是,就代码readability/structure而言,使用扩展函数是否有任何优势:
class Foo { ... }
fun Foo.bar() {
// Some stuff
}
相对于成员函数:
class Foo {
...
fun bar() {
// Some stuff
}
}
?
有推荐的做法吗?
何时使用成员函数
如果满足以下所有条件,您应该使用成员函数:
- 代码最初是用 Kotlin 编写的
- 您可以修改代码
- 该方法很有意义,可以从任何其他代码中使用
何时使用扩展功能
如果满足以下任一条件,您应该使用扩展函数:
- 代码最初是用Java写的,你想添加用Kotlin写的方法
- 您不能更改原始代码
- 您想要一个只对代码的特定部分有意义的特殊函数
为什么?
一般来说,成员函数比扩展函数更容易找到,因为它们保证在class它们是(或超级class/interface)的成员中。
它们也不需要导入到所有使用它们的代码中。
在我看来,使用扩展函数有两个令人信服的理由:
"extend" class 的行为你不是 / 的作者不能改变(继承没有意义或不是可能)。
为特定功能提供范围。例如,扩展函数可以声明为独立函数,在这种情况下它可以在任何地方使用。或者您可以选择将其声明为另一个 class 的(私有)成员函数,在这种情况下,它只能在 class.
内部使用
听起来 #1 在你的情况下不是问题,所以更多的是 #2。
扩展函数类似于您创建的实用函数。
一个基本的例子是这样的:
// Strings.kt
fun String.isEmail() : Boolean {
// check for email pattern and return true/false
}
这段代码可以写成 Java 中的效用函数,如下所示:
class StringUtils {
public static boolean isEmail(String email) {
// check for email pattern and return true/false
}
}
所以它本质上做的是,用你调用的对象调用同一个函数将作为第一个参数传递给参数。就像我在 Java
中给出的示例一样。
如果您想从java
调用在kotlin
中创建的扩展函数,您需要将调用者作为第一个参数传递。喜欢,
StringsKt.isEmail("example@example.com")
根据文档,
Extensions do not actually modify classes they extend. By defining an extension, you do not insert new members into a class, but merely make new functions callable with the dot-notation on variables of this type.
它们只是静态函数,调用者作为第一个参数,其他参数紧随其后。它只是扩展了我们以这种方式编写它的能力。
何时创建扩展函数?
- 当您无法访问该 class 时。当 class 属于您尚未创建的某个库时。
- 对于原始类型。 Int、Float、String 等
使用扩展函数的另一个原因是,您不必扩展 class 就可以使用这些方法,就好像它们属于 class (但实际上不是一部分其中 class)。
希望它能让你明白一点..
如其他答案中所述,扩展函数主要用于您无法更改的代码 - 也许您想将围绕某些库对象的复杂表达式更改为更简单、更易读的表达式。
我的做法是为 data classes
使用扩展函数。我的推理纯粹是哲学上的,data classes
应该只用作数据载体,它们不应该携带状态并且它们自己不应该做任何事情。这就是为什么我认为你应该使用扩展函数,以防你需要围绕 data class
.
编写函数
我知道 Kotlin 中使用扩展函数来扩展 class 的功能(例如,来自库或 API 的功能)。
但是,就代码readability/structure而言,使用扩展函数是否有任何优势:
class Foo { ... }
fun Foo.bar() {
// Some stuff
}
相对于成员函数:
class Foo {
...
fun bar() {
// Some stuff
}
}
?
有推荐的做法吗?
何时使用成员函数
如果满足以下所有条件,您应该使用成员函数:
- 代码最初是用 Kotlin 编写的
- 您可以修改代码
- 该方法很有意义,可以从任何其他代码中使用
何时使用扩展功能
如果满足以下任一条件,您应该使用扩展函数:
- 代码最初是用Java写的,你想添加用Kotlin写的方法
- 您不能更改原始代码
- 您想要一个只对代码的特定部分有意义的特殊函数
为什么?
一般来说,成员函数比扩展函数更容易找到,因为它们保证在class它们是(或超级class/interface)的成员中。
它们也不需要导入到所有使用它们的代码中。
在我看来,使用扩展函数有两个令人信服的理由:
"extend" class 的行为你不是 / 的作者不能改变(继承没有意义或不是可能)。
为特定功能提供范围。例如,扩展函数可以声明为独立函数,在这种情况下它可以在任何地方使用。或者您可以选择将其声明为另一个 class 的(私有)成员函数,在这种情况下,它只能在 class.
内部使用
听起来 #1 在你的情况下不是问题,所以更多的是 #2。
扩展函数类似于您创建的实用函数。
一个基本的例子是这样的:
// Strings.kt
fun String.isEmail() : Boolean {
// check for email pattern and return true/false
}
这段代码可以写成 Java 中的效用函数,如下所示:
class StringUtils {
public static boolean isEmail(String email) {
// check for email pattern and return true/false
}
}
所以它本质上做的是,用你调用的对象调用同一个函数将作为第一个参数传递给参数。就像我在 Java
中给出的示例一样。
如果您想从java
调用在kotlin
中创建的扩展函数,您需要将调用者作为第一个参数传递。喜欢,
StringsKt.isEmail("example@example.com")
根据文档,
Extensions do not actually modify classes they extend. By defining an extension, you do not insert new members into a class, but merely make new functions callable with the dot-notation on variables of this type.
它们只是静态函数,调用者作为第一个参数,其他参数紧随其后。它只是扩展了我们以这种方式编写它的能力。
何时创建扩展函数?
- 当您无法访问该 class 时。当 class 属于您尚未创建的某个库时。
- 对于原始类型。 Int、Float、String 等
使用扩展函数的另一个原因是,您不必扩展 class 就可以使用这些方法,就好像它们属于 class (但实际上不是一部分其中 class)。
希望它能让你明白一点..
如其他答案中所述,扩展函数主要用于您无法更改的代码 - 也许您想将围绕某些库对象的复杂表达式更改为更简单、更易读的表达式。
我的做法是为 data classes
使用扩展函数。我的推理纯粹是哲学上的,data classes
应该只用作数据载体,它们不应该携带状态并且它们自己不应该做任何事情。这就是为什么我认为你应该使用扩展函数,以防你需要围绕 data class
.