Class与KClass
扩展函数
基本使用
定义一个Person类
class Person{
}
在Expand.kt文件定义Person类扩展函数
fun Person.name(name: String) {
println(name)
}
fun Person.age(age: String) = println(age)
kotlin使用扩展函数
val person = Person()
person.name("zhang")
person.age("97")
java使用扩展函数
Person person = new Person();
ExpandKt.name(person,"zhang");
ExpandKt.age(person,"97");
扩展函数的静态解析
扩展函数支持多态吗?
扩展函数是静态添加的,不具有运行时的多态效应
open class Animal
class Dog : Animal()
fun Animal.name(): String = "animal"
fun Dog.name(): String = "dog"
fun Animal.printName(animal: Animal) {
println(animal.name())
}
fun main() {
val dog = Dog()
dog.printName(dog)
}
转为java,会强转为Animal,所以不支持多态
public static final void main() {
Dog dog = new Dog();
printName((Animal)dog, (Animal)dog);
}
Lambda
// lambda写法
var say = { name: String, age: Int ->
println("my name is $name,and I am $age")
}
// 函数写法
fun say1(name: String, age: Int): Unit {
println("my name is $name,and I am $age")
}
fun main() {
say("zhang", 97)
say1("zhang", 97)
}
my name is zhang,and I am 97
my name is zhang,and I am 97
最多22个参数
var sayMany = { p1: String, p2: String, p3: String,
p4: String, p5: String, p6: String, p7: String, p8: String, p9: String, p10: String, p11: String, p12: String,
p13: String, p14: String, p15: String, p16: String, p17: String, p18: String, p19: String, p20: String, p21: String,
p22: String//如果这里有p23:String,会报错说没有Function23
->
println("my name is $p1")
}
sayMany("a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a")
my name is a
新版本kotlin解决了这个问题,我的的这个版本参数是可以超越22的,原因如下
var sayMany = { p1: String, p2: String, p3: String,
p4: String, p5: String, p6: String, p7: String, p8: String, p9: String, p10: String, p11: String, p12: String,
p13: String, p14: String, p15: String, p16: String, p17: String, p18: String, p19: String, p20: String, p21: String,
p22: String, p23: String, p24: String
->
println("my name is $p1")
}
转为java
static {
say = (Function2)null.INSTANCE;//两个参数的
sayMany = (FunctionN)null.INSTANCE;//22参数以上的
}
高阶函数
// 高阶函数,参数或者返回值,是一个函数(或者Lambda)
fun onlyif(isDebug: Boolean, block: () -> Unit) {
if (isDebug) {
block()
}
}
fun main() {
onlyif(true) { println("打印日志") }
}
如何把函数作为参数传递给另一个函数:函数的引用
// 1. 定义一个runnable对象
val runnable = Runnable {
println("Runnable::run 这是一个函数引用 ::")
}
// 2. 声明一个函数叫做 function,这个函数类型是 ()->Unit
val function: () -> Unit
// 3. 现在要给function这个函数赋值,这个值必须也是一个函数,并且类型也是()->Unit
// function = runnable.run()//不能这样写,runnable.run()表示把执行结果赋值给了function
function = runnable::run//这就对了,把函数的引用赋值给function
onlyif(true, function)
Runnable::run 这是一个函数引用 ::
用内联优化代码 关键字:inline(类似于布局里的include)
对比下面的代码,区别只是在高阶函数onlyif之前加了一个inline
inline fun onlyif(isDebug: Boolean, block: () -> Unit) {
if (isDebug) {
block()
}
}
fun main() {
onlyif(true) { println("打印日志") }
}
fun onlyif1(isDebug: Boolean, block: () -> Unit) {
if (isDebug) {
block()
}
}
fun main() {
onlyif1(true) { println("打印日志") }
}
但是不建议到处使用inline,一般只是在高级函数前面使用,用他的目的是为了减少不必要的由Lambda表达式带来的匿名对象 过度使用inline会给编译器带来负担,查找问题变得复杂,不建议乱用这inline
构造函数
主构造函数
写在类声明的地方
open class Person(name: String)
class Man(name: String) : Person(name){
init {
println("构造函数执行时,我会执行的 $name")
}
}
fun main() {
Man("zhang")
}
次构造函数
如果由多个构造函数,第二个构造函数通过次构造函数实现,写到类内部
次构造函数,必须直接或间接调用该类主构造函数,或者改类的父类构造函数
open class Person(name: String)
class Man(name: String) : Person(name) {
private var age: Int = 0
private var address: String = ""
init {
println("构造函数执行时,我会执行的 $name")
}
constructor(name: String, age: Int) : this(name) {
this.age = age
}
constructor(name: String, age: Int, address: String) : this(name,age) {
this.address = address
}
}
fun main() {
Man("zhang")
Man("zhang", 97)
Man("zhang", 97, "beijng")
}
伴生对象
类似java静态
class StringUtils{
companion object{
fun isEmpty(str: String): Boolean {
return str.isEmpty()
}
}
}
fun main() {
val empty = StringUtils.isEmpty("")
}
如果java里想像静态一样使用这个伴生对象方法,要加上@Jvmstatic
class StringUtils {
companion object {
@JvmStatic
fun isEmpty(str: String): Boolean {
return str.isEmpty()
}
}
public class JavaC {
public static void main(String[] args) {
StringUtils.isEmpty("str");
}
}
使用伴生对象的单例模式写法(推荐写法)
当然直接使用object也行
class Single private constructor() {
companion object {
fun get(): Single {
return Holder.instance
}
}
private object Holder {
val instance = Single()
}
}
动态代理(by)
java 的写法是很繁琐的
interface Drive {
fun driving()
}
class MiShu : Drive {
override fun driving() {
println("我是秘书,我在开车。。。")
}
}
// Manager代理类,Mishu被代理类,他们都实现Drive接口
// 经理自己不用实现开车方法,,他是用的是秘书的开车方法
class Manager(drive: Drive) : Drive by drive {
}
fun main() {
Manager(MiShu()).driving()
}
我是秘书,我在开车。。。
interface Drive {
fun driving()
}
class MiShu : Drive {
override fun driving() {
println("我是秘书,我在开车。。。")
}
}
// Manager代理类,Mishu被代理类,他们都实现Drive接口
//一旦经理自己实现了开车方法,那么就是经历自己开车了
class Manager(drive: Drive) : Drive by drive {
override fun driving() {
println("我是经理,我在开车。。。")
}
}
fun main() {
Manager(MiShu()).driving()
}
我是经理,我在开车。。。