Kotlin学习 PART 2:kotlin基础

想了很久,一直在想怎么记录笔记最高效,最后感觉还是结合代码比较好。

1.整数的遍历,in表示是否在一个区间内,!in表示不再某个区间内

fun fizzBuzz(i:Int) = when {

    i%15==0->"FizzBuzz "

    i%3==0->"Fizz "

    i%5==0->"Buzz "

    else ->"$i "

}

>>>for(i in 100 downTo 1 step 2) {print(fizzBuzz(i))}

2.类似java,Pair的用法val list = arrayListOf("10", "11", "1001")

for((index, element) in list.withIndex()) {println("$index: $element")}

3.类似java中的.class

>>>println(set.javaClass)

***4.给别人的类添加方法:扩展函数和属性,注意包名要对

package strings 

fun:String.lastChar():Char = this.get(this.length()-1)

    接收者类型                    接收者对象

可以像调用类的普通成员函数一样去调用这个函数

>>>println("Kotlin".lastChar())

***扩展函数不能访问私有的或者是受保护的成员

5.导入和扩展函数

对于你定义的一个扩展函数,它不会自动地在整个项目范围内生效。相反,如果你要使用它,需要进行导入,(果然不出我所料),就像其他任何的类或者函数一样。Kotlin允许用和导入类一样的语法来导入单个的函数

import strings.lastChar或者import strings.*

val c ="Kotlin".lastChar()

用as来修改导入的类或者函数名称

import strings.lastChar as last

val c = "Kotlin".last()

6.不可重写的扩展函数

扩展函数并不是类的一部分,它是声明在类之外的。尽管可以给积累和子类都分别定义一个同名的扩展函数,此时需要调用时,会按照类的定义类型来判定到底会调用哪个函数。

fun View.showoff() = println("I'm a View!")

fun Button.showOff() = println("I'm a button!")


>>>val view:View = Button()

>>view.showOff()

I'm a View!

注意:扩展函数和成员函数同时存在时,成员函数的优先级要高于扩展函数。

        扩展函数相当于静态函数,所以不存在重写的问题。

7.字符串的分割split方法

按照正则表达式来进行分割

>>>println("12.345-6.A".split("\\.|-".toRegex)))

[12,235,6,A]

Kotlin中的split扩展函数的其他重载支持任意数量的纯文本字符串分隔符

>>>println("12.345-6.A".split(".", "-"))

输出结果相同

8.正则表达式和三重引用的字符串

fun parsePath(path:String) {

    

fun parsePath(path:String) {
    val directory = path.substringBeforeLast("/")
    val fullName = path.substringAfterLast("/")
    
    val fileName = fullName.substringBeforeLast(".")
    val extension = fullName.substringAfterLast(".")
    
    println("Dir: $directory, name: $fileName, ext: $extension")
}
fun parsePath(path:String) {
    val regex = """(.+)/(.+)\.(.+)""".toRegex()
    val matchResult = regex.matchEntire(path)
    if(matchResult != null)
    {
        val (directory, filename, extension) = matchResult.destructured
        println("")
    }
}

正则表达式写在一个三重引号的字符串中。在这样的字符串中,不需要对任何字符进行转义。

9.提取逻辑到扩展函数

class User(val id:Int, val name:String, val address:String)

fun User.validateBeforeSvae() {

    fun validate(value :String, fieldName:String) {
        if(value.isEmpty()) {
            throw IllegalArgumentException("Can't save user $id:empty $fieldName")
        }
    }
    validate(name, "name")
    validate(address, "address")
}

10.Kotlin的声明默认是final和public的。嵌套的类默认并不是内部类:他们并没有包含对其外部类的隐式引用。

    Kotlin编译器能够生成有用的方法来便面荣誉。将一个类声明成data类可以让编译器为这个类生成若干标准方法。

11.kotlin接口可以带默认实现,在一个类实现了两个接口,并且这两个接口拥有同一个名称的方法时,调用这个方法时,“任何一个都不会被调用”,需要显式地实现对应的方法。

override fun showOff() {
    super.showOff()
    super.showOff()
}

12.如果想创建一个类的子类,需要使用open修饰符来标示这个类。

注意:脆弱的基类问题,因为基类代码的修改不再符合在其子类中的假设。如果类没有提供子类应该怎么实现的明确规则(那些方法选用被重写及如何重写),当事人可能会有按基类作者预期之外的方式来重写方法的风险。因为不可能分析所有的子类,这种情况写基类是如此的脆弱,任何修改都有可能导致子类出现语气之外的行为改变。

13.internal可见性的优势在于它提供了对米小实现细节的真正封装。使用java时,这种封装很容易被破坏,因为外部代码可以将类定义到与你代码相同的包中,从而得到访问你的包私有声明的权限。

14.密封类:定义受限的类继承结构

使用when的时候,如果你添加了一个信息的子类,编译器并不能发现有地方改变了,如果你忘了添加一个新分支,就会选择默认的选项,这有可能导致潜在的bug。

kotlin解决方案,sealed类。

sealed class Expr {
    class Num(Val value:Int) :Expr()
    class Sum(Val left:Expr, val right:Expr):Expr()
}

fun eval(e:Expr) :Int = 
        when(e) {
            is Expr.Num -> e.value
            is Expr.Sum -> eval(e.right) + eval(e.left)
        }

sealed修饰符隐含的这个类是一个open类

Kotlin1.1解除了这些限制并允许在同一文件的任意位置定义子类


欲知后事如何,请听下回分解,enjoy yourselves!

你可能感兴趣的:(Kotlin学习 PART 2:kotlin基础)