类:class
定义属性会自动生成get 和set方法,也是属于空安全管理
//kotlin中的属性默认是private,并且字节码也默认初始化了get,set方法,要想改变
//个体,,set方法中的值,可以使用filed,相当于对获取到的属性进行二次加工
//属性:除非为可空类型,否则必须给值
class User {
var sex: String? = ""
get() = when (field) {
"0"-> "男"
"1" -> "女"
else -> "未知"
}
}
如果一个属性可变又可空,那么引用它之前必须保证它飞空
//初始化
//主构造函数:给属性进行赋值,临时变量以下划线开头,也可以定义属性
//次构造函数,必须继承主构造函数,次构造函数不可以定义属性,可以在代码块中处理传过来的数据
//构造函数的参数可以指定默认参数
//在调用对象时可以使用具名参数
//在调用对象时,如果该参数使用了默认参数,此参数可以传也可以不传
//初始化代码块:执行的顺序和主属性,哪个写在前面就先执行哪个
//延迟加载 initiate 判断是否被初始化 ::对象名.isInitialized
//继承 kotlin默认的类和方法都是不可以被继承或者被重写的,
// 如果要被继承或者被重写要使用open关键字在class之前
//使用is关键字判断类型
//使用as关键字进行强转
//智能类型转换,只要转过一次,后面就不需要强转
//Any,是所有类的超类,类似于java中的超类
class MainActivity : AppCompatActivity() {
@RequiresApi(Build.VERSION_CODES.N)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val p :Product = LuProduct()
println("fule-- ${p.name}")
}
}
open class Product(val name: String){
fun description() = "Product: $name"
open fun load () = "Nothing"//单表达式函数
}
class LuProduct : Product("kkk"){
override fun load () = "LuProduct loading..."
}
对象 :boject
使用object可以产生一个实例的类-单例
使用方式:
声明对象
对象表达式
伴生对象
//声明对象
//既是类名,又是实例名
object Applicationconfig{
}
//对象表达式
//有时候不一定非要定义一个新的命名类不可,也许你需要某个现有类的一种变体
//实例,但只是需要一个就行,事实上,对于这种用完就丢的类实例,连命名都可以省了,
//这里object就代表了一个子类,这样做是为了修改父类中的某一个方法
open class Player{
open fun load() = "oolllkkk"
}
fun main(){
val p = object :Player(){
override fun load() = "lllll"
}
}
//伴生对象
//使用场景:adapter里面的handler
//如果你想将某个对象的初始化和一个类实例捆绑在一起,可以考虑使用伴生对象
//使用companion修饰符,你可以在一个类定义里声明一个伴生对象,一个类里只能
//有一个伴生对象
open class ConfigMap{
//只有初始化configMap类或调用load函数时,伴生对象的内容才会载入
//而且无论实例化configMap类多少次,这个伴生对象始终只有一个实例存在
companion object{
private const val PATH = "KKK"
fun load() = File(PATH).readBytes()
}
}
数据类data
数据类是专门设计用来存储数据类的
数据类提供了tostring的个性化实现
==符号默认情况下,比较对象就是比较它们的引用值,数据类提供了equals和hashCode的个性化实现
copy
//copy
//对对象的某个值进行改变时,对象.copy然后改变某一个属性
//注意:copy就是new了一个新的对象,然后没有引用次构造函数,如果需要得再次给次构造的属性进行赋值
解构声明
一个普通的类如果要支持结构语法
数据类会直接支持结构语法
//解构语法
class PlayerScore(val exprience:Int,val level:Int){
operator fun component1() = exprience
operator fun component2() = level
}
val (x,y) = PlayerScore(10,20)
运算符重载
把数据类型的对象进行相加,其内部就是重写了+,-之类的方法
要使用operator重写plus方法
// + plus
// += plusAssign
// == equals
// > compareTo
// [] get
// .. rangeTo
// in contains
枚举类
enum class
可以添加构造函数和其他的函数
enum class Direction{
EAST,//EAST就相当于类的一个实例
WEST,
SOUTH,
NORTH
}
Direction.EAST //取出实例
Direction.EAST is Direction //判断是不是类的实例
enum class Direction(private val name1: String){
EAST("1"),//EAST就相当于类的一个实例,所以类如果有主构造方法的话,实例对象也要有
WEST("2"),
SOUTH("3"),
NORTH("4");
}
代数数据类型
可以用来表示一组子类型的闭集,枚举类就是一种简单的ADT
密封类
对于更复杂的ADT,你可以使用kotlin的密封类(sealed class)来实现更复杂的定义,密封类可以用来定义一个类似于枚举类的ADT,但你可以更灵活地控制某个子类型
密封类可以有若干个子类,要继承密封类,这些子类必须和它定义在同一个文件里
class MainActivity : AppCompatActivity() {
@RequiresApi(Build.VERSION_CODES.N)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val status = Lic.statu3("999")
val driver = Driver(status)
driver.checkLic()
}
}
sealed class Lic(){
object statu1 : Lic()//没有特殊操作的实例,使用object 单例
object statu2 : Lic()
class statu3 (val id :String): Lic() //具有特殊操作的实例,比如要在此实例状态下传id,所以需要创建实例,所以要使用class
}
class Driver (var status :Lic){
fun checkLic():String{
return when(status){
is Lic.statu1 ->"没资格"
is Lic.statu2 ->"在学"
is Lic.statu3 ->"有证 ID为 ${(this.status as Lic.statu3).id}"
}
}
}