Kotlin(四)方法的使用
一.方法的基本用法
1.声明
这里用onCreate方法为例来比较java和kotlin在声明方法时的不一样
java:
@override
public void onCreate(Bundle savedInstanceState) {
...
}
kotlin:
override fun onCreate(savedInstanceState: Bundle?) {
...
}
可以从这样一个重写方法看出:
- kotlin用override关键字放在方法名所在行行首来表明该方法重写自父类
- kotlin默认方法就是public,当方法为公有权限则不用指明public
- java中用void表明该方法无返回值,kotlin中没有void关键字,它的方法默认是没有返回值的
- kotlin方法的输入参数格式是“变量名:变量类型”
2.输入和输出参数
输入参数没什么好说的,其使用方式就和上述声明的一样,而且可以在变量类型后面加上?,表示在调用该方法时该输入参数可以为null。对于输出参数,如果方法存在返回值,那边就在fun fun1(x:Int)的后面以“:返回值类型”的方式来指明方法的返回值类型:
fun main():Int {
...
return 1
}
//前面提到过方法默认是没有返回值的,因为不加上":Int"方法确实无法指定返回值类型,但是没有返回值也是有规定的写法的
fun main():Unit {//我们往往直接不写:Unit
...
}
二.输入参数的变化
kotlin对于方法的输入参数在java的基础上提供了更多的功能
1.默认的输入参数
kotlin允许方法在声明时给输入参数一个默认值:
private fun funDemo1(first:Boolean, second:String = "str", third:Int = 0):String {
if (first && third == 1) {
return "$second"
} else {
return "error"
}
}
调用:
funDemo1(true)
那如果想修改默认的参数值,你就可以写成funDemo1(true, "123", 1),那如果我只想改第三个参数,第二个不变,那funDemo1(true, 1)这种写法是一定无法编译通过的,1这个参数值会默认去修改第二个参数的值,而第二个参数second是String类型,那么怎样去处理这种情况?kotlin允许在调用方法时显式的指明要修改的参数,即:funDemo1(true, third = 1)
2.可变参数
在java我们经常会遇到方法参数是同一类型的,但是参数个数是随机的,即public void method(String... args){...},然后我们在调用此方法时输入的参数个数可以是随机的,就相当于参数是一个未知长度的某类型数组。kotlin中用关键字vararg来完成这一功能:
private fun funDemo1(first:String, second:String, vararg array:Int?):String {
var str = "$first, $second"
for (item in array) {
str = "$str, ${item.toString()}"
}
return str
}
调用:
funDemo1("123", "123", 1, 2, 3)
三.特殊方法
1.泛型方法
kotlin中泛型方法的定义和java没有什么区别,命名方式:fun <T> method(first:String, vararg array:T?) {...},在调用时可不必显示的指明T是哪种类型,它可以根据传入的实参进行判断,当然显示指明会更好:method<Int>("123", 1, 2)或method("123", 1, 2)
2.内联方法
如果参数的类型都继承自某种类型,那么允许在定义方法时从这个指定的基类泛化开来,凡是继承自该类的子类都可以作为输入参数进行方法调用,比如说Int、Float、Double都继承自Number类,我们有一个method(array:Array<Number>)方法,它无法接收类型为Int、Float、Double的数组作为参数,这就需要泛型T来泛化基类Number,<T>改为<reified T: Number>,同时在fun之前加上关键字inline表示内联方法,只有内联方法才可以被具体化:
private inline fun <reified T: Number> funDemo2(array:Array<T>):String {
var str:String = "依次排列为:"
for (item in array) {
str = "$str$item,"
}
return str
}
调用上和普通的泛型方法没有区别:
funDemo2<Int>(整型数组对象)
3.简化方法
对于方法内逻辑简单且代码简短的方法,kotlin允许直接用等号给方法赋值:
tailrec fun funDemo3(n:Int):Int {
if (n <= 1) {
return n
} else
return n * funDemo3(n-1)
}
简化后:
fun funDemo3(n:Int):Int = if (n <= 1) n else n*funDemo3(n-1)
上述的示例方法是一个递归方法,你可能也注意到fun前面有一个tailrec关键字,这个关键字是指明该方法是尾递归方法,尾递归就是在返回值处重复调用自身方法,tailrec会告诉编译器这是一个尾递归方法,编译器会对该方法进行优化,会用循环的方式代替递归来避免栈溢出的情况
4.高阶方法
kotlin中允许方法A作为方法B的输入参数,方法B的入参内嵌了方法A,方法B就被称为高阶方法。扯不清楚还是写Demo吧:
private fun <T> funDemo3(array:Array<T>, compare10:(T) -> Boolean):String {
var maxStr:String = "大于10的数有:"
for (item in array) {
if (compare10(item)) {
maxStr += item
}
}
return maxStr
}
//compare10方法的具体逻辑要在调用funDemo3方法时实现
var array:Array<Int> = arrayOf(1, 13, 45, 41, 6)
funDemo3<Int>(array, {i -> print("运行成功");i>10})//i>10等同于if(i>10) true else false
该方法参数名是compare10,即compare10方法内嵌入funDemo3作为参数,compare10方法自身有一个泛型参数,返回值是Boolean类型。接着在调用funDemo3方法时以{... -> ...}这样一种lambda表达式的形式来写compare10方法的逻辑,i是compare10方法的形参,当i大于10则返回true。
来看一个更为简单明了的示例:
fun stringMapper(str: String, mapper: (String) -> Int): Int {
// Invoke function
return mapper(str)
}
stringMapper()
函数接受一个 String
以及一个函数,该函数根据您传递给它的 String
来推导 Int
值。
要调用 stringMapper()
,可以传递一个 String
和一个满足其他输入参数的函数(即,一个将 String
当作输入并输出 Int
的函数)这里的input仍然是一个形参,如以下示例所示:
stringMapper("Android", { input ->
input.length
})
如果匿名函数是在某个函数上定义的最后一个参数,则您可以在用于调用该函数的圆括号之外传递它,如以下示例所示:
stringMapper("Android") { input ->
input.length
}
OK,一般情况下我们可能会用到的方法知识差不多就这些,自己用kotlin的时间也不长,哪些地方说的不对请各位大佬务必指出,下一篇来说类和对象Kotlin(5)类与对象_我们间的空白格的博客-优快云博客