Kotlin开发指南深入浅出KotlinKotlin

浅谈Kotlin语法篇之变量和常量(二)

2018-04-26  本文已影响32人  熊喵先森
android_kotlin.png

这次所说的是Kotlin的变量和常量,主要会对以下内容做介绍:

一、Kotlin与Java中变量和常量 使用对比

public String name = "Mikyou";//定义变量
public final int age = 18;//final定义常量
var name: String = "Mikyou"
val age: Int = 18

或者

var name = "Mikyou"
val age = 18

总结: 由以上的对比可得出:

二、Kotlin的变量和常量用法

var name: String = "Mikyou"
var address: String?//如果这个变量没有初始化,那么需要显示声明类型并且指明类型是否可null
address = "NanJing"
val age: Int = 18

或者

var name = "Mikyou"
val age = 18

三、Kotlin的自定义属性访问器

在Kotlin中属性是头等特性,它习惯于用一个属性去替代Java中的字段和setter,getter方法。而Kotlin中的set、get访问器相当于Java中的setter,getter方法。Kotlin有个新的特性就是可以去定义一个类中属性的访问器包括setter,getter访问器。该特性十分适用于需要经过多个属性逻辑计算得出的一个新的属性。那么逻辑计算的过程操作不需要像Java一样开一个方法来实现。可以直接在属性访问器中进行逻辑运算。

在Java中实现:

public class Rectangle {

    private float width;
    private float height;

    public Rectangle(float width, float height) {
        this.width = width;
        this.height = height;
    }

    public boolean isSquare() {//在java中实现一个方法进行相关的逻辑计算
        return width == height;
    }

}

在Kotlin中实现:

class Rectangle(width: Float, height: Float) {
    val isSquare: Boolean//在Kotlin中只需要一个属性就能解决,重新定义了isSquare的getter属性访问器,访问器中可以写入具体逻辑代码。
        get() {
            return width == height
        }
}

在Java中实现Android中的一个自定义View中的setter方法。

public class RoundImageView extends ImageView {
        ...
    
    public void setBorderColor(int color) {
        mColor = color;
        invalidate();
    }
        ...
}

在Kotlin中实现Android中的一个自定义View中的set属性访问器。

class RoundImageView @JvmOverloads constructor(context: Context, attributeSet: AttributeSet? = null, defAttrStyle: Int = 0)
    : ImageView(context, attributeSet, defAttrStyle) {

    var mBorderColor: Int
        set(value) {//自定义set属性访问器
            field = value
            invalidate()
        }
}

四、Kotlin中的var和val区别

五、Kotlin中val不可变与可读的讨论

由于Kotlin是一门新的语言,我们在学习的过程中经常习惯性的去记住一些所谓定理,而没有去真正深究为什么是这样。比如拿今天的议题来说,相信很多的人都这样认为(刚开始包括我自己)var修饰的变量是可变的,而val修饰的变量是不可变的。然后学完Kotlin的自定义属性访问器就会觉得是有问题的。然后去看一些国外的博客,虽然有讲述但是看完后更让我懵逼的是val修饰的变量的值是可以变化的可读的,并且底层的引用也是变化的。前面那句确实可以理解,后面一句还是保留意见。于是乎就开始写demo认证。
引用国外博客的一句原话"But can we say that val guarantees that underlying reference to the object is immutable? No…" 国外博客源地址

假设一: 在Kotlin中的val修饰的变量不能说不可变的,只能说val修饰变量的权限是可读的。

假设二: 在Koltin中的val修饰的变量的引用是不可变的,但是指向的对象是可变的。

论证假设一: 我们在Kotlin的开发过程中,一般是使用了val修饰的变量就不能再次被赋值了,否则就会抛出编译时的异常。但是不能再次被赋值不代表它是不可变的。因为Kotlin与Java不一样的是多了个自定义属性访问器的特性。这个特性貌似就和val修饰的变量是不可变的矛盾了。而Java中不存在这个问题,如果使用了final修饰的变量,没有所谓自定义访问器概念。

fun main(args: Array<String>) {
    val name = "Hello Kotlin"
    name = "Hello Java"
}

print error:

Error:(8, 5) Kotlin: Val cannot be reassigned

定义get属性访问器例子

class RandomNum {
    val num: Int
        get() = Random().nextInt()
}

fun main(args: Array<String>) {
    println("the num is ${RandomNum().num}")
}

print result:

the num is -1411951962
the num is -1719429461

总结: 由以上的例子可以说明假设一是成立的,在Kotlin中的val修饰的变量不能说是不可变的,而只能说仅仅具有可读权限。

论证假设二: 由论证一,我们知道Kotlin的val修饰的变量是可变的,那它的底层引用是否是可变的呢?国外一篇博客说引用是可变的,真是这样吗?通过一个例子来说明。

User类:

package com.mikyou.kotlin.valtest
open class User() {
    var name: String? = "test"
    var age: Int = 18
    var career: String? = "Student"
}

Student类:

class Student() : User()

Teacher类:

class Teacher() : User()

Customer接口:

interface Customer {
    val user: User//注意: 这里是个val修饰的User实例引用
}

VipCustomer实现类:

class VipCustomer : Customer {
    override val user: User
        get() {
//            return Student().apply {
//                name = "mikyou"
//                age = 18
//                career = "HighStudent"
//            }
            return Teacher().apply {
                //看到这里很多人肯定认为,底层引用也会发生改变,毕竟Student, Teacher是不同的对象了。但是事实是这样的吗?
                name = "youkmi"
                age = 28
                career = "HighTeacher"
            }
        }
}

测试:

fun main(args: Array<String>) = VipCustomer().user.run {
    println("my name is $name, I'm $age years old, my career is $career, my unique hash code is ${hashCode()} ")
}

print result:

my name is mikyou, I'm 18 years old, my career is HighStudent, my unique hash code is 666988784 
    
//切换到Teacher
my name is youkmi, I'm 28 years old, my career is HighTeacher, my unique hash code is 666988784

总结: 由以上的例子可以说明假设二是成立的,两个不同的对象hashCode一样说明,user的引用地址不变的,而变化的是引用指向的对象是可以变化的。

到这里Kotlin入门基础语法就结束了,下一篇将会继续深入Kotlin相关内容

qrcode_for_gh_109398d5e616_430.jpg

欢迎关注Kotlin开发者联盟,这里有最新Kotlin技术文章,每周会不定期翻译一篇Kotlin国外技术文章。如果你也喜欢Kotlin,欢迎加入我们~~~

上一篇 下一篇

猜你喜欢

热点阅读