Funciones estándar de Kotlin:
Función estándar let
fun main() {
val student = Student("lucky", 19);
study(student)
}
fun study(student: Student?) {
study?.doHomework()
study?.readBooks()
}
En el aprendizaje de Kotlin - tipo de sistema anulable , si el parámetro de entrada es anulable, debe agregarse cada vez que se llama a la función del objeto en la función ?.
, y la escritura del código es demasiado engorrosa. En este momento, puede combinar ?.
operadores y let
funciones para optimizar el código, como se muestra a continuación:
fun main() {
val student = Student("lucky", 19);
study(student)
}
fun study(student: Student?) {
student?.let {
s ->
s.doHomework()
s.readBooks()
}
}
?.
El operador significa no hacer nada cuando el objeto está vacío y llamar let
a la función cuando el objeto no está vacío. Cuando estaba haciendo la optimización de la expresión lamda antes ( aprendizaje de Kotlin - colección ): cuando solo hay un parámetro en la lista de parámetros de la expresión Lambda, no es necesario declarar el nombre del parámetro, pero se puede usar la palabra clave it en su lugar, por lo que el código anterior se puede optimizar hacia abajo:
fun main() {
val student = Student("lucky", 19);
study(student)
}
fun study(student: Student?) {
student?.let {
it.doHomework()
it.readBooks()
}
}
let
Además de ayudarnos a simplificar el juicio no nulo, los subprocesos múltiples también pueden controlar el juicio nulo de las variables globales.
var student: Student? = null
fun study() {
if (student !=null){
student.doHomework()
student.readBooks()
}
}
El código anterior compilará e informará un error, porque el valor de la variable global puede ser modificado por otros subprocesos en cualquier momento Incluso si se realiza el juicio nulo, aún no puede garantizar que la variable if
en la declaración student
no tenga riesgo de nulo puntero. Utilice let
la función para modificar:
var student: Student? = null
fun study() {
student?.let {
it.doHomework()
it.readBooks()
}
}
Después de que desaparezca el error y se juzgue que la variable no está vacía, ejecute la declaración en let. let puede asegurarse de que la variable no esté vacía student
durante la ejecución de la declaración lambda .student
Resumen: let
Puede ayudarnos a simplificar el juicio no nulo, y también puede controlar el juicio nulo de variables globales en subprocesos múltiples.
función estándar con
fun main() {
val fruits = listOf("apple", "banana", "pear")
println(fruitPrint(fruits))
}
Hay una lista de frutas arriba, y el requisito es unirlas en un formato fijo. El método de implementación habitual es el siguiente:
fun fruitPrint(fruits: List<String>): String {
val fruitPrint = StringBuilder();
fruitPrint.append("My favorite fruits are : \n")
for (f in fruits) {
fruitPrint.append(f).append("\n")
}
fruitPrint.append("----- end -----")
return fruitPrint.toString()
}
//打印结果
My favorite fruits are :
apple
banana
pear
----- end -----
El objeto se llama varias veces seguidas donde se empalma la cadena StringBuilder
. Para este escenario, podemos usar with
funciones para simplificar el código.
fun fruitPrint(fruits: List<String>): String {
return with(StringBuilder()) {
append("My favorite fruits are : \n")
for (f in fruits) {
append(f).append("\n")
}
append("----- end -----")
toString()
}
}
Si with
se pasa un objeto como primer parámetro de la función StringBuilder
, el contexto de toda la expresión de Lambda será este StringBuilder
objeto. Entonces podemos llamar directamente append()
y toString()
método en la expresión Lambda. La última línea de código de la expresión lambda se with
devuelve como valor de retorno de la función.
Resumen: cuando se requieren operaciones frecuentes en el mismo objeto, with
se pueden usar funciones para simplificar el código.
ejecución de función estándar
run
El uso de funciones with
es muy similar a las funciones, pero run
las funciones generalmente no se llaman directamente, sino que se llaman sobre la base de un objeto. Y with
hay dos parámetros de entrada, run
solo un parámetro de entrada de expresión Lambda.
Del mismo modo, la última línea de código en la expresión lambda de with
y se devuelve como valor de retorno.run
El ejemplo anterior se puede run
reescribir como una función:
fun fruitPrint(fruits: List<String>): String {
return StringBuilder().run {
append("My favorite fruits are : \n")
for (f in fruits) {
append(f).append("\n")
}
append("----- end -----")
toString()
}
}
aplicación de la función estándar
apply
Las funciones run
son similares a las funciones, deben invocarse en un objeto y solo recibir un parámetro Lambda, y el contexto del objeto invocador también se proporcionará en la expresión Lambda, pero la función de aplicación no puede especificar el valor de retorno, sino que lo hará automáticamente. devolver el objeto de llamada en sí.
fun fruitPrint(fruits: List<String>): String {
val sb = StringBuilder().apply {
append("My favorite fruits are : \n")
for (f in fruits) {
append(f).append("\n")
}
append("----- end -----")
}
return sb.toString()
}
Dado que apply
la función no puede especificar el valor de retorno, solo puede devolver el objeto de llamada en sí, por lo que no se puede devolver directamente.Nuestro valor de retorno declara el tipo String, por lo que debe convertirse.
Veamos el uso en Android:
val intent = Intent(this,MainActivity::class.java).apply {
putExtra("data1","data1")
putExtra("data2",2)
putExtra("data3",true)
}
startActivity(intent)
Al iniciar MainActivity, puede ir a Intent
los parámetros contenidos en la configuración.
función estándar también
El uso de also es similar al de apply, vea un ejemplo:
fun studentInfoCheck(s: Student) {
s.also {
it.name = "Lucky" }
println(s.name)
}
Usado internamente it
para referirse al contexto, se puede realizar una serie de operaciones sobre el objeto. El valor de retorno apply
solo puede devolver el objeto de llamada en sí.
Diferencias en funciones estándar
¿Estás confundido por aprender aquí? Comparemos las diferencias de las siguientes funciones y se verá más claro.
función estándar | contexto interno | valor de retorno |
---|---|---|
dejar | él | La última línea de código en el bloque let |
con | esto (se puede omitir) | La última línea de código en el bloque let |
correr | esto (se puede omitir) | La última línea de código en el bloque let |
aplicar | esto (se puede omitir) | llamar al objeto mismo |
también | él | llamar al objeto mismo |
La diferencia entre con y correr
De la tabla anterior, el contexto interno y el valor de retorno with
de y run
son los mismos, entonces, ¿cuál es la diferencia entre los dos?
with
Hay dos parámetros de entrada,run
solo un parámetro de entrada de expresión Lambda;- Los métodos de evaluación de la seguridad aérea son diferentes;
Para el segundo punto, echemos un vistazo al caso:
fun printStudentInfo() {
val s: Student? = null
with(s) {
this?.name = "Tom"
this?.age = 4
}
print(s)
}
Lo anterior es para usar with
el juicio vacío. Al usarlo, debe juzgar el no vacío nuevamente cada vez, cámbielo run
para probar
fun printStudentInfo() {
val s: Student? = null
s?.run {
name = "Tom"
age = 4
}
print(s)
}
En primer lugar, run
la llamada a la función omite this
la referencia, y la verificación de seguridad vacía se lleva a cabo en la capa externa, y solo cuando no está vacía puede ingresar al bloque de funciones para operar Student
. En comparación with
, run
las funciones son más simples y las comprobaciones de seguridad nulas son menos with
frecuentes.
Artículo de referencia
Diferencias entre let, run, with, apply y también en Kotlin