文章目录
- 一、internal
- 二、infix
- 三、object
- 四、open
- 五、operator
- 六、sealed class
- 1. 用法一
- 2. 用法二
- 七、typealias
- 八、when
- 1. 带参数
- 2. 不带参数
一、internal
internal
修饰方法,表示这个方法只适合当前 module 使用,同理修饰 class 也是一样。
@Synchronized internal fun executed(call: RealCall) {runningSyncCalls.add(call)
}
二、infix
2023-7-7 11:01:19
Kotlin允许在不使用括号和点号的情况下调用函数,那么这种函数被称为 infix函数(中缀函数)。
定义 infix 函数,需要满足以下要求
- 它们必须是成员函数或扩展函数;
- 它们必须只有一个参数;
- 其参数不得接受可变数量的参数且不能有默认值。
class Util(val number:Int) {infix fun sum(other: Int) {println(number + other)}
}fun main(){val u = Util(5)u sum 5 // 10u sum 7 // 12
}
请注意,中缀函数总是要求指定接收者与参数。当使用中缀表示法在当前接收者上调用方法时,需要显式使用 this;不能像常规方法调用那样省略
class MyStringCollection {infix fun add(s: String) { /* …… */ }fun build() {this add "abc" // 正确add("abc") // 正确add "abc" // 错误:必须指定接收者}
}
中缀函数与操作符的优先级
-
中缀函数调用的优先级低于算术操作符、类型转换以及 rangeTo 操作符
1 shl 2 + 3 等价于 1 shl (2 + 3) 0 until n * 2 等价于 0 until (n * 2) xs union ys as Set<*> 等价于 xs union (ys as Set<*>)
-
中缀函数调用的优先级高于布尔操作符 && 与 ||、is- 与 in- 检测以及其他一些操作符
a && b xor c 等价于 a && (b xor c) a xor b in c 等价于 (a xor b) in c
三、object
类和对象同时创建,相当于 懒汉式单例,里面的方法是 final 方法
- val 变量相当于 private static final
- var 变量相当于 private static
kotlin中有四种方式表示静态:
- object单例类模式
- companion object
- JvmStatic注解模式
- 顶层函数模式
object:反编译java代码是由一个静态类包含一系列非静态函数
companion object:同上
JvmStatic:只能注解在单例或companion object 中的方法上,反编译java代码是一个静态函数
顶层函数:反编译java代码是一个静态函数
四、open
2023-7-7 09:51:24
在java中允许创建任意的子类并重写任意的方法,除非显示的使用了final关键字进行阻止。
而在kotlin的世界里面则不是这样,在kotlin中它所有的类默认都是 final
的,那么就意味着不能被继承,而且在类中所有的方法也是默认是final
的,那么就是kotlin的方法默认也不能被重写,所以open
关键字就是用来解决这个现象的。
五、operator
2023-1-16 14:00:13
operator
:重载修饰符。重载运算符以达到修改原有的运算逻辑输出调用者需要的结果
常见的运算符
运算符 | 运算重载表示 |
---|---|
a+b | a.plus(b) |
a-b | a.minus(b) |
a*b | a.times(b) |
a/b | a.div(b) |
a%b | a.rem(b) 或 a.mod(b) |
a…b | a.rangeTo(b) |
++a, a++ | inc |
!a | not |
a>b | a.compareTo(b)>0 |
a<b | a.compareTo(b)<0 |
a<=b | a.compareTo(b)>=0 |
a<=b | a.compareTo(b)<=0 |
a in b | b.contains(a) |
a !in b | !b.contains(a) |
重载plus
比如上面的 a+b
,我们在使用时候除了使用这种方式还可以使用运算重载表示a.plus(b)
,但是需要提前定义好函数
// 一定要使用 operator 修饰 plus 函数,否则无法使用 + 号
class My(val a:Int){operator fun plus(b:Int):Int{return a*b // 也可以使用 a.times(b) --> kotlin默认运算符重载表示(Primitives.kt)}
}// 使用
fun main(){val a = My(3)val plus = a.plus(3)val i = a + 4println(i)println(plus) // 输出// 12, 9
}
重载get
operator
除了可以重载运算符号,还可以重载get
class My(val a:Int){val arr = mutableListOf(1,2,3,4)operator fun get(index:Int):Int{return arr[index+1]}
}
// 使用
fun main(){val a = My(3)val get = a.get(0)// 也可以是 val get = a[0]println(get)// 输出 2
}
六、sealed class
2023-7-19 16:54:58
sealed class,密封类。具备最重要的一个特点:
其子类可以出现在定义 sealed class 的不同文件中,但不允许出现在不同的 module 中,且需要保证 package 一致。这样既可以避免 sealed class 文件过于庞大,又可以确保第三方库无法扩展你定义的 sealed class,达到限制类的扩展目的。
1. 用法一
是一个有特定数量子类的类,看上去和枚举有点类似。
// TestSealed.ktsealed class GameAction(times: Int) {// Inner of Sealed Classobject Start : GameAction(1)data class AutoTick(val time: Int) : GameAction(2)class Exit : GameAction(3)}//与内部类的创建一样
fun main(args:Array<String>){var sc:GameAction = GameAction.Start()
}
2. 用法二
2023-11-21 星期二
可以实现普通类无法实现的 条件判断语句。
sealed class Result
class Success(val code: Int) : Result()
class Exception(val code: Int, val message: String) : Result()fun handleResult(result: Result): String{return when(result) {is Success -> {"success"}is Exception -> {"exception"}}
}
反编译后的java代码,Result
类其实是一个抽象类,Success
和 Exception
继承了这个抽象类。Result
类的构造函数是私有的,不能在外部访问到。
通过继承这个抽象类,达到限制类型的做法。
这其实和 java 中使用接口来限定参数类型的做法类似,很好理解。
七、typealias
2023-10-27 20:34:13
别名。和 import as 很像,但两者使用范围有差别,具体查看链接。
- typealias 只能定义在顶层位置,不能被内嵌在类、接口、函数等内部(import as)。
kotlin中的别名:
@SinceKotlin("1.1") public actual typealias ArrayList<E> = java.util.ArrayList<E>
@SinceKotlin("1.1") public actual typealias LinkedHashMap<K, V> = java.util.LinkedHashMap<K, V>
@SinceKotlin("1.1") public actual typealias HashMap<K, V> = java.util.HashMap<K, V>
@SinceKotlin("1.1") public actual typealias LinkedHashSet<E> = java.util.LinkedHashSet<E>
@SinceKotlin("1.1") public actual typealias HashSet<E> = java.util.HashSet<E>
多数通用场景:
// Classes and Interfaces (类和接口)
typealias RegularExpression = String
typealias IntentData = Parcelable// Nullable types (可空类型)
typealias MaybeString = String?// Generics with Type Parameters (类型参数泛型)
typealias MultivaluedMap<K, V> = HashMap<K, List<V>>
typealias Lookup<T> = HashMap<T, T>// Generics with Concrete Type Arguments (混合类型参数泛型)
typealias Users = ArrayList<User>// Type Projections (类型投影)
typealias Strings = Array<out String>
typealias OutArray<T> = Array<out T>
typealias AnyIterable = Iterable<*>// Objects (including Companion Objects) (对象,包括伴生对象)
typealias RegexUtil = Regex.Companion// Function Types (函数类型)
typealias ClickHandler = (View) -> Unit// Lambda with Receiver (带接收者的Lambda)
typealias IntentInitializer = Intent.() -> Unit// Nested Classes and Interfaces (嵌套类和接口)
typealias NotificationBuilder = NotificationCompat.Builder
typealias OnPermissionResult = ActivityCompat.OnRequestPermissionsResultCallback// Enums (枚举类)
typealias Direction = kotlin.io.FileWalkDirection
// (but you cannot alias a single enum *entry*)// Annotation (注解)
typealias Multifile = JvmMultifileClass
八、when
2024-1-5 16:46:17 星期五
1. 带参数
fun mix(color1: ColorEnum, color2: ColorEnum) =when(setOf<ColorEnum>(color1, color2)){setOf(ColorEnum.RED, ColorEnum.GREEN) -> "黄色"setOf(ColorEnum.RED, ColorEnum.BLUE) -> "紫色"setOf(ColorEnum.BLUE, ColorEnum.GREEN) -> "黑色"else -> throw Exception("不知道什么颜色")
}
2. 不带参数
带参数的会好理解一些,根据when的条件去做判断,最终给出符合条件的输出。但是不带参数的,我们做了验证,结果如下:谁先成立执行谁,并跳出判断。
class CustomBean{val conditon1=trueval conditon2=trueval conditon3=false
}fun main(){val cb = CustomBean()when{cb.conditon1-> l2.i("Splash","conditon1")cb.conditon2-> l2.i("Splash","conditon2")else-> l2.i("Splash","else")}
}/*输出:
conditon1
*/
看下反编译后的java代码,所以相当于 if else ,谁先成立执行谁,并跳出判断。
public static void main(String[]args){CustomBean cb = new CustomBean();if (cb.getConditon1()) {l2.i("Splash", "conditon1");} else if (cb.getConditon2()) {l2.i("Splash", "conditon2");} else {l2.i("Splash", "else");}
}