专栏首页Android NoteKotlin For Android 笔记(二)

Kotlin For Android 笔记(二)

1、当方法参数不定的时候,我们可以使用 vararg 声明,这样就可以传入多个值了;但每个方法只能声明一个 vararg
fun printSum(vararg numbers: Int) {
    val sum = numbers.sum()
    print(sum)
}
printSum(1,2,3,4,5) // Prints: 15
printSum() // Prints: 0

// 可以直接传递数组(但是要以 * 为前缀)
val texts=arrayOf("b","c","d")
printAll(*texts)
2、当 when 的参数为空时,可以省略 ()
                                                  // 这里省略了 `()`
override fun onOptionsItemSelected(item: MenuItem?)=when{
        item?.itemId==R.id.design_menu_item_action_area->{
            onBackPressed()
            true
        }
        else -> super.onOptionsItemSelected(item)
}
3、Default arguments value versus Named arguments syntax
fun printValue(value: String, inBracket: Boolean = true,prefix: String = "", suffix: String = "") {
    print(prefix)
    if (inBracket) {
        print("(${value})")
     } else {
        print(value)
    }
    println(suffix)
}

printValue("str", true, "","") // Prints: (str)
printValue("str") // Prints: (str)
printValue("str", false) // Prints: st

//命名式参数
printValue("str", suffix = "!") // Prints: (str)!
四、Top-level function

使用 Android 项目,Kotlin 被编译成运行在 Dalvik 上的 Java 字节码。虚拟机(安卓 5.0 之前)或安卓运行时(安卓 5.0 及更高版本)。两个虚拟机都只能执行类内定义的代码。为了解决这个问题,Kotlin 编译器为顶级函数生成类。这个类名由 文件名kt 后缀构成。在这样的 class 里函数和属性是静态的。例如,假设我们定义了 printer.kt 文件中的函数:

// Printer.kt
fun printTwo() {
    print(2)
}

将 kotlin 代码编译成 Java 字节码。生成的字节码将类似于下面的 Java 类生成的代码:

//Java
public final class PrinterKt { // 1
  public static void printTwo() { // 2
      System.out.print(2); // 3
    }
}

1、printerkt 是由 文件名kt 后缀组成的名称。 2、所有顶级函数属性都编译为静态方法和变量。 3、print 是一个 kotlin 函数,但由于它是一个内联函数,因此它的调用被替换为 它在编译期间的主体。它的主体只包含 system.out.println 的调用

我们还可以在 Java 文件中访问 Kotlin 顶级函数。用类名前缀函数调用:

//Java file, call inside some method
PrinterKt.printTwo()

正如我们所看到的,Kotlin 与 Java 是可以互操作的。为了使 Kotlin 的顶级方法,在 Java 中使用更加方便,我们可以添加一个可以更改名称的 annotation (这个注解一定要放在 package 的上面) 一个 JVM 生成的类。这样在 Java 中调用 Kotlin 的顶级方法和属性是很方便的。类似下面这样:

@file:JvmName("Printer")

接着就可以在 Java 文件使用了。Printer.printTwo()

五、Local functions(局部方法)
fun makeStudentList(): List<Student> {
    var students: List<Student> = emptyList()
  fun addStudent(name: String, state: Student.State =  Student.State.New) {
    students += Student(name, state, courses = emptyList())
  }
  // ...
  addStudent("Adam Smith")
  addStudent("Donald Duck")
  // ...
  return students
}

这样写有一个好处就是,可以直接使用当前方法的变量,不需要去传递;如果把它提取为成员方法,那就需要传递所需要的参数,如果调用修改了参数的形式,那函数的声明也需要重新修改,这样就导致了要修改两个地方(Java 中经常出现这样的问题)。

六、自定义 getter/setter
class Student {
    var age: Int?//自定义 get/set 方法
        get() = age
        set(value) {//value 是自定义的变量名,名字可以随便起
            age = value
        }
}

image.png

这样会爆出堆栈错误!!!让我们来看一下 Student 的 class 文件

image.png

果然,造成了堆栈溢出(recursive call)

这时候使用 Kotlin 提供的备用字段(关键字 field)即可解决这个问题

class Student {
    var age: Int? = 0
        get() = field //使用备用字段自定义 get/set 方法
        set(value) {
            field = value
        }
}

再次查看 class 文件发现代码也正常了

image.png

备用字段 field 的使用范围仅限于当前属性的 get/set 方法。

以下两种情况不支持 field (写了也没效果)字段

① 因为第一次类创建的时候,属性的值就被计算了(后续的值不会再起作用)

class Fruit(var weight: Double) {
    val isHeavy = weight > 20
}
    var fruit = Fruit(7.0)
    println(fruit.isHeavy) // Prints: false
    fruit.weight = 30.5
    println(fruit.isHeavy) // Prints: false

② 因为它的值总是使用另一个属性计算的。

class Car {
    var usable: Boolean = true
    var inGoodState: Boolean = true
    var crashed: Boolean
    get() = !usable && !inGoodState
    set(value) {
      usable = false
      inGoodState = false
  }
}

如果类没有主构造函数,而超类有一个非空的构造函数,然后每个次构造函数必须使用 super 关键:

class ProductView : View {
    constructor(ctx: Context) : super(ctx)
    constructor(ctx: Context, attrs : AttributeSet) super(ctx, attrs)
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • [译] 带你领略 ConstraintLayout 1.1 的新功能前言带你领略 ConstraintLayout 1.1 的新功能

    code_horse
  • Android—Room 数据库迁移(Migration)

    code_horse
  • Kotlin —  Sealed Classes(密封类)

    code_horse
  • ML.NET介绍:最常使用的数据结构IDataView

    ML.NET一种跨平台的开源机器学习框架。ML.NET将让广大.NET开发人员可以开发自己的模型,并且将自定义的机器学习融入到其应用程序中,无需之前拥有开发或调...

    程序你好
  • Android Studio移动鼠标显示悬浮提示的设置方法

    以Windows 10 + Android Studio 3.0.1为例 默认情况下,在Android Studio中将鼠标移动到函数位置处无法显示悬浮提示,需...

    用户1221057
  • 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 使用FairyGUI (一)

    用户1687945
  • AutoMagic使用说明

    自动化测试管理平台,可以进行用户、产品、项目、模块、测试用例、测试元素、测试关键字、测试报告的管理等。

    苦叶子
  • 20110612 DiscuzNT代码研

    2) 通过页面隐藏模型重写Discuz.Web-install-index.aspx页面

    用户2398817
  • python+rsync精确同步指定格式

    用户2398817
  • 屌丝必看案例:加州大学光棍极客通过大数据搞定女朋友

    在加州大学洛杉矶分校数学楼5层的一个阁楼里,显示器上闪烁着微弱的灯光。Chris McKinlay正在使用罗拉多州超算为他博士论文(大规模数据处...

    小莹莹

扫码关注云+社区

领取腾讯云代金券

玩转腾讯云 有奖征文活动