美文网首页
Kotlin(三)—类和接口

Kotlin(三)—类和接口

作者: CodingSnail | 来源:发表于2018-02-22 10:19 被阅读0次

1、构造器

在Kotlin中,类允许定义一个主构造器(primary constructor)和若干个第二构造器(second constructor),主构造器是类头的一部分,紧跟在类名的后面,构造器参数是可选的,主构造器的初始化需要在init快中进行初始化,主构造器的参数可以是val和var第二构造器参数是只读的,不能在构造器内容改变参数的值。要注意的是,即使使用var声明变量,在构造器内容修改参数变量值后,并不会把修改的值传到对象外部,以下是构造器的例子演示。

class StudyCommanapy(var url: String) {

    init {
        println(url)
    }

    constructor(value: Int) : this("com.codingnail") {
        println(value)
    }

    constructor(description: String, url: String) : this("[" + url + "]") {
        println(description + ":" + url)
    }

    constructor() : this(20) {
        println("<https://com.codingsnail.test>")
    }


}
fun main(args: Array<String>) {
    StudyCommanapy("https://codingsnail.com")
    println("******************************************************")
    StudyCommanapy(100)
    println("******************************************************")
    StudyCommanapy("个人博客网站", "https://codingsnail.com")
    println("******************************************************")
    StudyCommanapy()
}

https://codingsnail.com
******************************************************
com.codingsnail
100
******************************************************
[https://codingsnail.com]
个人博客网站:https://codingsnail.com
******************************************************
com.codingsnail
20
<https://com.codingsnail.test>

2、单例模式

class Singleton private constructor() {

    public var value: Singleton? = null

    private object mHolder {
        val INSTANCE = Singleton()
    }

    companion object Factory {
        fun getInstance(): Singleton {
            return mHolder.INSTANCE
        }
    }
}

fun main(args: Array<String>) {
//   Singleton()  Error(21,2) Cannot access'<init>' : it is private in 'Singleton'
    var obj1 = Singleton.getInstance()
    var obj2 = Singleton.getInstance()
    println(obj1)
    println(obj2)
}

运行结果如下:
Singleton@5305068a
Singleton@5305068a

3、Kotlin函数的默认参数

class Student(val name: String = "liang", var age: Int = 23)

fun main(args: Array<String>) {

    val student = Student()
    println("我的名字是:${student.name},我的年龄是${student.age}")
}

运行结果如下:
我的名字是:liang,我的年龄是23

Kotlin是调用了Student()的主构造器创建了Student()类的实例,但实际上,是调用了另一个自动生成的构造器,并在构造器中指定了所有的默认参数值。

4、和Java属性的区别

public class Student {

    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

Kotlin中支持属性语法,只有var/val和propertyName(属性名)是必须的,其它都是可选的,引用属性就和引用变量一样。

class Student {

    var name: String = "liang"
    var age: Int = 23

    fun descStudent() {
        println("我的名字是:${name},我的年龄是${age}")
    }
}

fun main(args: Array<String>) {

    val student = Student()
    student.descStudent()
}

运行结果如下:
我的名字是:liang,我的年龄是23

Kotlin也提供了专门的getter()和setter()方法,只是写法上比较麻烦

class Student {

    val name: String
        get() = "liang"

    var v: Int = 23
    var age: Int
        get() = v
        set(value) {
            v = age
        }

    fun descStudent() {
        println("我的名字是:$name,我的年龄是$age")
    }
}

fun main(args: Array<String>) {

    val student = Student()
    student.descStudent()
}

运行结果如下:
我的名字是:liang,我的年龄是23

当然面对这种繁琐的方法,Kotlin也提供了更便捷的方式来解决这个问题,这就是field字符,在属性的getter和setter中,将field当做成员变量使用,也就是通过field读写属性 ,就算是提供了field的写法,感觉写法上还是很啰嗦。

class Student {

    val name: String
        get() = "liang"

    var age: Int = 0
        get() = field
        set(value) {
            println("学生年龄属性被更改")
            field = value
        }
}

fun main(args: Array<String>) {

    val student = Student()
    student.age = 28
    println("学生年龄更改后的值为:${student.age}")
}

运行结果如下:
学生年龄属性被更改
学生年龄更改后的值为:28

5、函数

在Kotlin中,函数既可以在类外部定义,也可以在类内部定义,如果是前者,是全局函数,如果是后者,是类成员函数,函数也支持默认参数值,需要注意的是,带默认值的参数必须是最后几个参数,也就是说,如果某个参数带默认值,那么该参数后面的所有参数必须都有默认值。

class Student {

    fun descStudent(name: String, age: Int = 23, weight: Float = 70.0f, height: Float = 183.5f) {
        println("${name}的年龄是${age},体重是${weight}KG,身高${height}cm")
    }
}

fun main(args: Array<String>) {

    val student = Student()
    student.descStudent("小明")
}

运行结果如下:
小明的年龄是23,体重是70.0KG,身高183.5cm

如果我们的Student对象里面有很多属性,但是我们只希望改变最后一个,那么之前有默认值的我们都需要去改变

 student.descStudent("小明",23,70.0f,187f)

这样的话很繁琐,Kotlin提供了带参数名传递值的方法,可以为制定的参数传值

 student.descStudent("小明",height=187f)

运行结果如下:
小明的年龄是23,体重是70.0KG,身高187.0cm

Kotlin如果有不确定的参数的时候使用vararg 进行修饰

class Students {

    fun addStudents(vararg students: Student): List<Student> {
        val list = ArrayList<Student>()
        for (student in students)
            list.add(student)
        return list
    }
}

函数体只有一样代码的时候,使用传统的写法比较麻烦可以使用单行表达式,直接返回值

6、嵌套类

class Outer1 {

    class TestInner {
        fun test() = "custom write"
    }
}

class Outer2 {

    inner class Test {
        fun test() = "inner write"
    }
}

fun main(args: Array<String>) {
    println(Outer1.TestInner().test())
    println(Outer2().Test().test())
}

运行结果如下:
custom write
inner write

7、修饰符

private 仅仅在类的内部可以访问
protected 类和子类中可以访问
internal 同一个Module的类可以访问
public 任何类都可以访问

Kotlin默认class是final的,默认时class不允许被继承,需要使用open修饰类才可以

open class TestFather {
    // 当被final修饰时,不能被子类重写
    //final  fun getName() = "snail"
    //方法名必须加上open才能被子类重写
    open fun getName() = "snail"
}
class TestSon : TestFather() {

    override fun getName(): String {
        return super.getName()
    }
}

Kotlin 接口使用interface声明,接口中的属性和方法都是open的
抽象类与接口非常类似,Kotlin接口支持默认函数体,抽象类不能被实例化,需要使用abstract关键字声明,抽象类实现接口后,接口中没有函数体的函数可以不重写,接口中的这些方法就自动继承到实现接口的抽象类中,称为抽象方法。

相关文章

网友评论

      本文标题:Kotlin(三)—类和接口

      本文链接:https://www.haomeiwen.com/subject/druatftx.html