1、类的定义

如何定义一个类。与Java类似的是,它需要一个class关键字.
class Track {
}

它有一个默认并且唯一的构造器,你只需要在类名后面加上参数:
class Track(json: String) {
     //如果这个类没有任何的内容,则可以省略花括号
}
如果默认构造函数有注解或者可见性修饰符,那么需要加入构造器的关键词
class Track private constructor(json: String) {
}
当然你还可以增加其他的次要构造器。
两种写法
class Track {
    constructor(json: String) {
    }
}

class Track(json: String) {
     constructor(json: String, id: Int): this(json) {
     }
}
也就是说,如果该类没有申明默认构造体的时候,次要构造体可以用第一种写法。如果申明了默认构造体,所有的次要构造体都要引用默认构造体,类似Java中的super

那么构造函数的函数体写在哪里呢?
class Track(json: String) {
     init {
     JSONObject job = new JSONObject(json)
     ......
     }
}

2、类的继承

Kotlin中默认的类都是基础继承至Any,类似Java中的Object。默认都是final状态,不可继承。当关键字是open或者abstract的时候,是可以继承的。
open class Track(json: String)
class TrackM(json: String, type: Int) : Track(json)
当我们只有当个构造器时,需要在从父类继承下来的构造器中指定需要的参数。类似super()

3、实例化

和Java的实例化类似,不同的是,Kotlin实例化对象省略了new关键字。

4、Data Class

在开发中,我们会创建一个model包,然后创建了很多model类,应用在各个页面。而这些model类,其实做的事情很少,声明属性,提供setter和getter方法。但是却写了非常多行的代码,甚至任何一个属性名的改变,都要去修改对应的方法,否则json的解析便有可能出错。在Kotlin中,提供了一个更加简介的写法。
     data class User(val name:String,val age:Int)
同样的,它提供了一些默认的方法。
  • equals()/hashCode() pair
  • toString() of the form "User(name=John, age=42)"
  • componentN() functions corresponding to the properties in their order of declaration
  • copy() function
在使用这个类的时候,需要注意一下几点
  • 主构造函数必须要有至少一个的入参(如果想要实现无参调用,只需要为所有入参设置初始值)
  • 主构造的入参必须要标记成val或者var
  • data class不能有abstract, open, sealed or inner修饰符
  • 在1.1以前data class只能实现接口,之后的能实现其他类
关于copy函数
val vip1 = Vip(1"Tom"20)_____Vip(number=1, name=Tom, age=20)
val vip2 = vip1.copy(2)__________Vip(number=2, name=Tom, age=20)
val vip2 = vip1.copy(age = 40)___Vip(number=1, name=Tom, age=40)
也就是说,copy函数的入参是可选的,如果不指定参数名,默认是选择第一个参数。

关于componentN()函数
这个函数非常有趣和方便,主要用在拆解构造函数上面
val (a, b, c) = vip1
只要这么一些,原先vip1的三个入参,可以直接使用a、b、c。当然参数只能少不能多,并且是按顺序的,跟你的命名无关。这种语法成为解构声明。如果你在解构声明中你不需要某个变量,那么可以用下划线取代。
val (a, _, c) = vip1

5、Sealed Class

Sealed Class被用在描述限制继承的类,当一个值可能是某个优先集合的类型中,但不能是此外的任何类型的时候,我们就可以用到了。常用在switch case中。
sealed class Expr
data class Const(val number: Double) : Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()

fun eval(expr: Expr): Double = when(expr) {
    is Const -> expr.number
    is Sum -> eval(expr.e1) + eval(expr.e2)
    NotANumber -> Double.NaN
}
这里就不需要用到else了的判断语句块了,因为所有继承自Expr的类都覆盖到了。

6、范型

这里就不需要用到else了的判断语句块了,因为所有继承自Expr的类都覆盖到了。
class Box<T>(t: T) {
    var value = t
}

val box = Box<Int>(0)
val box = Box(0)
如果编译器能够判断范型的类型,那么你无须指定类型,否则必须要给定你要的类型。

7、嵌入式类

class Outer { private val bar: Int = 1 class Nested { fun foo() = 2 }}
inner class可以调用外部类的成员,并持有它的一个object
class Outer { private val bar: Int = 1 inner class Inner { fun foo() = bar }}
匿名内部类,如果匿名内部类只有一个抽象函数,则可以使用lambda表达式简化写法
window.addMouseListener(object: MouseAdapter() { override fun mouseClicked(e: MouseEvent) { // ... } override fun mouseEntered(e: MouseEvent) { // ... }})

val listener = ActionListener { println("clicked") }

8、代理

8.1  代理类
interface Base {
    fun print()
}

class BaseImpl(val x: Int) : Base {
    override fun print() { print(x) }
}

class Derived(a: Base) : Base by a

val b = BaseImpl(10) 
Derived(b).print() // prints 10

区别于继承,它不用去实现接口。

8.2 代理属性
思考一个场景,我们希望监听某个属性是否调用了set/get方法,并给出响应。如果在Java中,我们可能需要在被监听的属性的settter和getter方法中去写代码,一个还好,十个、五十个,那就多了。有没有更好的接替思路呢?有的,代理,我们把settter和getter方法给别人做,这样的话,代理告诉我它调没调用这个方法。

class Delegate {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return "$thisRef, thank you for delegating '${property.name}' to me!"
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        println("$value has been assigned to '${property.name} in $thisRef.'")
    }
}

class Example {
    var p: String by Delegate()
}

调用这个方法。
val e = Example()println(e.p)—————————> Example@33a17727, thank you for delegating ‘p’ to me!
e.p = "NEW" —————————> NEW has been assigned to ‘p’ in Example@33a17727.
     
一些标准的Kotlin代理:
  • lazy 懒加载。第一次调用时候会调用get方法,如果初始化成功,那么下一次调用将会直接记住上一次的值,如果失败,则会继续初始化。
  • Obeservable。用来观测属性值的改变过程。
  • map。

9、单例模式的几种写法

      在Kotlin的类中没有静态成员,也就是说你不能创建静态方法或者变量。那么我们该怎么写单例模式呢?

a.懒人写法
object Lazy {
}

相比java代码

public class Lazy {
    private static Lazy instance new Lazy();
    private Lazy() {}
    public static Lazy getInstance() {return instance;}
}
但是这种写法会在类加载时候就新建实例,拖慢应用启动速度。

b.懒加载
class LazyNotThreadSafe {
    companion object {
        //写法一:Kotlin上原生写法
        //lazy关键字表示只有在这个instance被调用的时候才会调这个构造方法
        //LazyThreadSafetyMode.NONE 不是线程安全
        val instance by lazy(LazyThreadSafetyMode.NONE{
            LazyNotThreadSafe()
        }

        //写法二:Java转译
        private var instance1: LazyNotThreadSafe? = null

        fun newInstance(): LazyNotThreadSafe {
            if (instance1 == nullinstance1 = LazyNotThreadSafe()
            return instance1!!
        }
    }
}

相比java代码

public class Lazy {
    private static Lazy instance;
    private Lazy() {}
    public static Lazy getInstance() {
        if (instance == null)
            instance new Lazy();
        return instance;
    }
}

c.加锁
class LazySychronized private constructor() {
    companion object {
        private var instance: LazySychronized? = null

        @Synchronized
        fun newInstance(): LazySychronized {
            if (instance == nullinstance = LazySychronized()
            return instance!!
        }
    }
}

d.Double Check
class DoubleCheck private constructor() {
    companion object {
        val instance by lazy(LazyThreadSafetyMode.SYNCHRONIZED{
            DoubleCheck()
        }
    }
}

public class SingleDoubleCheck {
    //volatile保证赋值和构造是有序的
    private static volatile SingleDoubleCheck instance;
    private SingleDoubleCheck() {}
    public static SingleDoubleCheck getInstance() {
        if (instance == null) {
            synchronized (SingleDoubleCheck.class) {
                if (instance == null) {
                    //保证实例化和赋值顺序
                    instance new SingleDoubleCheck();
                }
            }
        }
        return instance;
    }
}

e.静态内部类
class InnerClass private constructor() {
    private object Holder {
        val instance = InnerClass()
    }

    companion object {
        fun newInstance() = Holder.instance
    }
}

public class InnerClass {
    private static class Holder {
        private static InnerClass instance new InnerClass();
    }

    private InnerClass() {}

    public static InnerClass getInstance() {return Holder.instance;}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值