kotlin-2-类

1、kotlin 可见性修饰符

Java有四种:

  • public:包内及包外的任何类均可以访问
  • protected:包内的任何类,及包外的那些继承了此类的子类才能访问
  • 默认:包内的任何类都可以访问它,包外的任何类都不能访问
  • private:包内包外的任何类均不能访问

Kotlin也是有四种:

  • public:默认值,什么都不写表示是public。
  • protected:和Java不同的是,即使在同一个包内,也不能访问protected方法。比private多了子类可以调用这一范围。
  • internal:所在的整个 module 可见
  • private:只在这个类内部可见。
2、kotlin 主构造函数

主构造函数 写在类头中 如果你不希望别的类访问到这个变量,可以用private修饰

class Person constructor(firstName: String) {
}

如果主构造函数没有注解或可见性说明,则 constructor 关键字是可以省略:
class Person (firstName: String) {
}

如果构造函数有注解或可见性声明,则 constructor 关键字是不可少的,并且可见性应该在前
class Customer public @inject constructor (name: String) {...}

主构造函数不能包含任意代码。初始化代码可以放在以 init 做前缀的初始化块内
class Person (firstName: String) {
  init {
        logger,info("Customer initialized with value ${firstName}")
    }
}

总结

  • 主构造函数 constructor写在类头中 ,没有修饰符或者注解修饰可以省略constructor关键字
  • 主构造函数中,如果参数加var会自动生成对应的属性
  • 主构造函数中,如果你不希望别的类访问到这个变量,可以用private修饰
  • init代码块也属于主构造器的一部分,也可以引用主构造函数中的变量
  • 如果没有主构造函数,也会隐式地创建一个无参构造函数,
  • 创建对象不需要 new
3、kotlin 次构造函数

类也可以有二级构造函数,需要加前缀 constructor:

  • 次级构造函数不能直接将参数转换为属性(不能加var)
  • 如果有主构造器,那么次构造器必须直接或者间接引用到主构造器
    在同一个类中代理另一个构造函数使用 this 关键字:
class Person(var firstName: String) {

    init {
        println("Customer initialized with value ${firstName}")
    }
    //var firstName: String? = null

    constructor() : this("Xiao ming")

    //不能直接将参数转换为字段,
    constructor(firstName: String, lastName: String) : this(firstName) {
        this.lastName = lastName
    }

    var lastName: String? = null

}
4、 重写get set方法

声明一个属性的完整语法是
var [: ] [= ]
[]
[]

其初始器(initializer)、getter 和 setter 都是可选的。属性类型如果可以从初始器 (或者从其 getter 返回值,如下文所示)中推断出来,也可以省略。

var allByDefault: Int?    *错误:需要显式初始化器,隐含默认 getter 和 setter
var initialized = 1  * 类型 Int、默认 getter 和 setter

在主构造函数中 初始器(initializer) 才可以省略
class User {

    constructor(name: String, sex: Int) {
        this.name = name
        this.sex = sex
    }

    var name: String? = null
    var sex: Int? = null
        set(value) {
            // 此处 如果调用 sex 赋值 会造成死循环 sex=0
            if (0 == value) { // 正确
                sexStr = "男"
            } else {
                sexStr = "女11"
            }
        }
    var sexStr: String? = null
//        get() {
//            // 此处 如果调用 sexStr 取值 会造成死循环 if ("".equals(sexStr))
//            if (0 == sex) { // 正确
//                return "男"
//            }
//            return "女"
//        }

}

一般不需要重写get set方法,在某些特定场景下重写即可,但注意避免死循环

5、 继承

kotlin 中所有的类和方法默认都是final,不能直接继承或者重写,如果要继承或重写,需要加上open 关键字

open class Parent(var name: String) {

    var sex: String? = null

    init {
        this.name = "人"
    }

    // 没有加open关键字,不能重写
    fun showParent() {

    }

    // 加open关键字可以重写
    open fun showSelf() {

    }
}

class Child( name: String):Parent (name){

    // 没有加open关键字,不能重写
//    fun showParent(){
//
//    }
    // 重写加 override  一般写法不换行
    override  fun showSelf(){

    }
}
6、 接口

接口用关键字 interface 来定义:
个类或对象可以实现一个或多个接口

interface TestInterface {

    //可以在接口中声明属性,但属性必须是抽象的 或 提供访问实现。
    //private var name: Int   //这种写法错误
    //var name: String? = null  //这种写法错误
    var name: String
    abstract var sex: Int
    fun test()
}
class TestInterfaceImpl(override var name: String, override var sex: Int) : TestInterface {
    override fun test() {
        println(name+"--"+sex)
    }
}

接口中声明的,必须是抽象的 或 提供访问实现

7、 抽象
abstract class A {
    //abstract val  name: String ? = null   写法错误
    //val  name: String ? = null    写法正确
    abstract val  name: String     //写法正确

    //抽象类里已经提供实现的方法 要想被重写必须加open
    open fun test() {
        println(name)
    }
    abstract fun testNobody()
    //抽象类里的方法,可以不提供提供实现的时候需要用abstract关键字来描述 抽象的方法默认是open的
}
class B:A() {

    override val  name: String=""
    override fun test() {
        println(name)
    }
    override fun testNobody(){
    }
}

抽象类里,抽象的方法默认是open的,非抽象方法是final的
可以不提供提供实现的时候需要用abstract关键字来描述
抽象类里 可以有属性,属性必须是非null的或者抽象的

8、可以使用默认参数来实现java重载类似的功能
    //函数参数可以设置默认值,当参数被忽略时会使用默认值。这样相比其他语言可以减少重载
    fun reformat(name: String, sex: Boolean = true,age: Int= 18) {

    }
    reformat("TOM")
    reformat("Tom", true, 18)
9、data

在Kotlin中一些只保存数据的类,称为数据类(data class),
为了确保自动生成的代码一致性和有意义,数据类(data class)必须满足以下要求:

  • 主构造函数至少有一个参数;
  • 主构造函数的所有参数需标记为val 或 var;
  • 数据类不能是抽象、开放、密封或者内部的;

编译器会为数据类(data class)自动生成以下函数:

  • equals()/hashCode()
  • toString() 默认输出"User(name=John, age=42)"
  • componentN() 按声明顺序对应于所有属性
  • copy()
10、copy
  • 当要复制一个对象,只改变一些属性,但其余不变,copy()就是为此而生:
        data class DataUser(val name: String, val age: Int)
        val u = DataUser(name = "lioil", age = 1)
        val u1 = u.copy("win")   //传递第一参数,第二参数默认
        val u2 = u.copy("win",2) //传递所有参数
        val u3 = u.copy(age = 3) //命名参数,传递指定参数
        println("$u1,$u2,$u3")

DataUser(name=win, age=1),DataUser(name=win, age=2),DataUser(name=lioil, age=3)
11、apply
  • apply函数,在函数范围内,可以任意调用该对象的任意方法,并返回该对象
data class DataUser(val name: String, var age: Int){
    fun test (){
        println("test")
    }
}

val u = DataUser(name = "lioil", age = 1)
val u1 =  u.apply {
       age = 15
       test()
}
println("$u1")

mame 是无法修改的 因为是val

你可能感兴趣的:(kotlin-2-类)