kotlin 基本语法(二)

十二, kotlin控制语句

1, if else 语句

// 传统用法
var max = a 
if (a < b) max = b

// 使用 else 
var max: Int
if (a > b) {
    max = a
} else {
    max = b
}
 
// 作为表达式
val max = if (a > b) a else b //类似于java中的三元运算符, kotlin中没有三元运算符

//  我们也可以把 IF 表达式的结果赋值给一个变量。

val max = if (a > b) {
    print("Choose a")
    a
} else {
    print("Choose b")
    b
}

使用区间  使用 in 运算符来检测某个数字是否在指定区间内,区间格式为 x..y :
val x = 5 
val y = 9 
if (x in 1..8) { 
   println("x 在区间内") 
}

2,  When 表达式 类似于Java中的switch表达式, 但是远比它强大, 支持所有数据类型

// 其最简单的形式如下: 

when (x) {
    1 -> print("x == 1")
    2 -> print("x == 2")
    else -> { // 注意这个块 在打括号内可以执行多行代码
        print("x 不是 1 ,也不是 2")
    }
}

//  在 when 中,else 同 switch 的 default。如果其他分支都不满足条件将会求值 else 分支。

//  如果很多分支需要用相同的方式处理,则可以把多个分支条件放在一起,用逗号分隔:

when (x) {
    0, 1 -> print("x == 0 or x == 1")
    else -> print("otherwise")
}

//  检测一个值在(in)或者不在(!in)一个区间或者集合中: 

when (x) {
    in 1..10 -> print("x is in the range")
    in validNumbers -> print("x is valid")
    !in 10..20 -> print("x is outside the range")
    else -> print("none of the above")
}

// 另一种可能性是检测一个值是(is)或者不是(!is)一个特定类型的值。注意: 由于智能转换,

// 你可以访问该类型的方法和属性而无需 任何额外的检测。

fun hasPrefix(x: Any) = when(x) {
    // is 类似于Java中的instanceof 用来判断数据类型 和java不同的是, 使用is判断过类型后, 不用再强转数据类型, 
    // 可以智能转换
    is String -> x.startsWith("prefix") 
    else -> false
}

// when 也可以用来取代 if-else if链。 如果不提供参数,所有的分支条件都是简单的布尔表达式,

// 而当一个分支的条件为真 时则执行该分支:

when {
    x.isOdd() -> print("x is odd")
    x.isEven() -> print("x is even")
    else -> print("x is funny")
}

3, for循环, for 可以循环遍历任何提供了迭代器的对象。 数组, 区间(0..10), 集合, Map等

 语法: 

for (item in collection) {
   print(item)
}

通过索引遍历数组

for (i in array.indices) {
    print(array[i])
}

对集合进行遍历

val items = listOf("apple", "banana", "kiwi")
for (item in items) {
    println(item)
}

for (index in items.indices) {
    println("item at $index is ${items[index]}")
}

正常循环 1..4 或者1 until 5(不包含5)

for (i in 1..4) print(i) // 打印结果为: "1234"

反序循环  4 downTo 1  包含头和尾

for (i in 4 downTo 1) print(i) // 打印结果为: "4321"

也支持指定步长:关键字:step

for (i in 1..4 step 2) print(i) // 打印结果为: "13"

for (i in 4 downTo 1 step 2) print(i) // 打印结果为: "42"

4, while 与 do...while 循环, return,  break,contine 和java一样,

标签处返回, 稍有区别

fun foo() {//显式标签
    ints.forEach lit@ {
        if (it == 0) return@lit
        print(it)
    }
}
fun foo() {
    ints.forEach {//隐式标签
        if (it == 0) return@forEach
        print(it)
    }
} 

十三,  类和对象

1, 类定义

class Person { //默认public权限 // 大括号内是类体构成 }

2, 定义一个空类  

class Empty

 3, 在类中定义成员函数:

class Runoob() { fun foo() { print("Foo") } // 成员函数 }

 4, 属性定义

class Person{

     var name: String = "wwf" //默认public

     private var age: Int= 12//私有的属性

}

5, 创建类实例: 

val person= Person() // Kotlin 中没有 new 关键字
//属性调用
person.name

 

6, Koltin 中的类可以有一个 主构造器,以及一个或多个次构造器,主构造器是类头部的一部分,位于类名称之后:

如果主构造器没有任何注解,也没有任何可见度修饰符,那么constructor关键字可以省略。

class Person constructor(firstName: String) {//主构造器
} 
//等价于
class Person(firstName: String) {} 

没有主函数, 也可以如:自定义线性布局 ,继承使用 : 接口和类都是 : 类后面要添加(), 接口不用
class MyLinearLayout : LinearLayout {
    
    constructor(context: Context) : super(context) {//次构造器

    }

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {//次构造器

    }

    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : 
             super(context, attrs, defStyleAttr) {//次构造器

    }
}
//等价于 有主构造函数, 可以不写次构造函数,@JvmOverloads 关键字告诉虚拟器生成java代码, 会生成java的三个构造函数
class MyLinearLayout @JvmOverloads constructor(
        context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
    ) : LinearLayout(context, attrs, defStyleAttr){}

7, getter 和 setter 

属性声明的完整语法:

var <propertyName>[: <PropertyType>] [= <property_initializer>]
    [<getter>]
    [<setter>]
var initialized = 1    // 类型为 Int, 默认实现了 getter 和 setter 可读可写
val inferredType = 1   // 类型为 Int 类型,默认实现 getter 只读属性

实例:

class Person {

    var lastName: String = "zhang"
        get() = field.toUpperCase()   // 将变量赋值后转换为大写
        set

    var no: Int = 100
        get() = field                // 后端变量
        set(value) {
            if (value < 10) {       // 如果传入的值小于 10 返回该值
                field = value
            } else {
                field = -1         // 如果传入的值大于等于 10 返回 -1
            }
        }

    var heiht: Float = 145.4f
        private set
}

// 测试
fun main(args: Array<String>) {
    var person: Person = Person()

    person.lastName = "wang"

    println("lastName:${person.lastName}")

    person.no = 9
    println("no:${person.no}")

    person.no = 20
    println("no:${person.no}")

}

 8, 非空属性必须在定义的时候初始化,kotlin提供了一种可以延迟初始化的方案,使用 lateinit 关键字描述属性:

class MyLinearLayout @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr) {

    private lateinit var mContext: Context//成员属性 不可为空
    
    private lateinit var mText: String//成员属性 不可为空 
    //也可以这样声明 private var mText : String? = null 可空属性
    
    fun setText(text: String) {
        this.mText = text
    }
    init {//构造函数初始化
        this.mContext = context
    }
    fun test(){
     //声明时, 带? 使用时, 也要带? 和Java if(mText == null){} 等价
     //使用lateinit(延迟初始化, 使用前, 必须初始化, 否则报异常)声明的变量使用时, 不用加? 但是会报空指针异常
      mText?.plus("你好")
    }
   
}

9, 抽象类, 抽象是面向对象编程的特征之一,类本身,或类中的部分成员,都可以声明为abstract的。

      抽象成员在类中不存在具体的实现。

      注意:抽象类和接口, 默认是open修饰的, 普通类默认final类, 不能被继承。 所有类, 不加public默认都是public权限

     open class Base {

       open fun f() {

       }

     }

     abstract class Derived : Base() { 

        override abstract fun f()

     }

10,嵌套类

class Outer {                  // 外部类
    private val bar: Int = 1
    class Nested {             // 嵌套类
        fun foo() = 2
    }
}

fun main(args: Array<String>) {
    val demo = Outer.Nested().foo() // 调用格式:外部类.嵌套类.嵌套类方法/属性
    println(demo)    // == 2
}

11, 内部类

 内部类使用 inner 关键字来表示。

内部类会带有一个对外部类的对象的引用,所以内部类可以访问外部类成员属性和成员函数。

class Outer {
    private val bar: Int = 1
    var v = "成员属性"
    /**嵌套内部类**/
    inner class Inner {
        fun foo() = bar  // 访问外部类成员
        fun innerTest() {
            var o = this@Outer //获取外部类的成员变量
            println("内部类可以引用外部类的成员,例如:" + o.v)
        }
    }
}

fun main(args: Array<String>) {
    val demo = Outer().Inner().foo()
    println(demo) //   1
    val demo2 = Outer().Inner().innerTest()   
    println(demo2)   // 内部类可以引用外部类的成员,例如:成员属性
}

12, 匿名内部类 

class Test {
    var v = "成员属性"

    fun setInterFace(test: TestInterFace) {
        test.test()
    }
}

/**
 * 定义接口
 */
interface TestInterFace {
    fun test()
}

fun main(args: Array<String>) {
    var test = Test()

    /**
     * 采用对象表达式来创建接口对象,即匿名内部类的实例。
     */
    test.setInterFace(object : TestInterFace {
        override fun test() {
            println("对象表达式创建匿名内部类的实例")
        }
    })
}

click点击事件

mTextView?.setOnClickListener {//大括号内使用 it 代指调用者
   //里面处理点击事件
}

13, 修饰符

 类的修饰符包括 classModifier 和_accessModifier_:

// classModifier: 类属性修饰符,标示类本身特性。

kotlin                                       java
abstract    // 抽象类                         abstract
final       // 类不可继承,默认属性            final
enum        // 枚举类                         enum
open        // 类可继承,类默认是final的       没被final修饰的类
annotation  // 注解类                         annotation

accessModifier: 访问权限修饰符

kotlin                                       java
private    // 仅在同一个文件中可见             private
protected  // 同一个文件中或子类可见           protected
public     // 所有调用的地方都可见             public
internal   // 同一个模块中可见                 没有修饰符,

十四, 继承 Any所有类的超类, 类似于java中的Object

Kotlin 中所有类都继承该 Any 类,它是所有类的超类,对于没有超类型声明的类是默认超类:

class Example // 从 Any 隐式继承

Any 默认提供了三个函数: 

equals()

hashCode()

toString()

 如果一个类要被继承,可以使用 open 关键字进行修饰。

open class Base(p: Int)           // 定义基类

class Derived(p: Int) : Base(p)

如果子类有主构造函数, 则基类必须在主构造函数中立即初始化。 

open class Person(var name : String, var age : Int){// 基类

}

class Student(name : String, age : Int, var no : String, var score : Int) : Person(name, age) {

}

// 测试
fun main(args: Array<String>) {
    val s =  Student("Runoob", 18, "S12346", 89)
    println("学生名: ${s.name}")
    println("年龄: ${s.age}")
    println("学生号: ${s.no}")
    println("成绩: ${s.score}")
}

 子类没有主构造函数

如果子类没有主构造函数,则必须在每一个二级构造函数中用 super 关键字初始化基类,或者在代理另一个构造函数。初始化基类时,可以调用基类的不同构造方法。

class Student : Person {

    constructor(ctx: Context) : super(ctx) {
    } 

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

重写: 在基类中,使用fun声明函数时,此函数默认为final修饰,不能被子类重写。如果允许子类重写该函数,那么就要手动添加 open 修饰它(抽象函数除外, 默认是open的), 子类重写方法使用 override 关键词:

/**用户基类**/
open class Person{
    open fun study(){       // 允许子类重写
        println("我毕业了")
    }
}

/**子类继承 Person 类**/
class Student : Person() {

    override fun study(){    // 重写方法
        println("我在读大学")
    }
}

fun main(args: Array<String>) {
    val s =  Student()
    s.study();

}

属性重写 :

属性重写使用 override 关键字,属性必须具有兼容类型,每一个声明的属性都可以通过初始化程序或者getter方法被重写:

open class Foo {
    open val x: Int get { …… }
}

class Bar1 : Foo() {
    override val x: Int = ……
}

 

你可以用一个var属性重写一个val属性,但是反过来不行。因为val属性本身定义了getter方法,重写为var属性会在衍生类中额外声明一个setter方法

你可以在主构造函数中使用 override 关键字作为属性声明的一部分:

interface Foo {
    val count: Int
}

class Bar1(override val count: Int) : Foo

class Bar2 : Foo {
    override var count: Int = 0
}

十五, 接口 

Kotlin 接口与 Java 8 类似,使用 interface 关键字定义接口,允许方法有默认实现

interface Demo{
    fun add(a:Int, b:Int):Int    // 未实现
    fun minus(a: Int, b: Int): Int {  //已实现
        return a - b
    }
}

一个类或者对象可以实现一个或多个接口

class SubDemo: Demo{

    override fun add(a:Int, b:Int) : Int {

         // 方法体

    }

}

接口中的属性只能是抽象的,不允许初始化值,接口不会保存属性值,实现接口时,必须重写属性

interface Demo {
    var name:String 
}

class SubDemo : Demo{
    override var name:String = "wwf"//重写属性
}

函数重写: 实现多个接口时,可能会遇到同一方法继承多个实现的问题。例如:

interface Demo1{
    fun foo() { print("A") }   // 已实现
    fun bar()                  // 未实现,没有方法体,是抽象的
}

interface Demo2 {
    fun foo() { print("B") }   // 已实现
    fun bar() { print("bar") } // 已实现
}

class Demo3 : Demo1 {
    override fun bar() { print("bar") }   // 重写
}

class Demo4 : Demo1, Demo2 {
    override fun foo() {
        super<Demo1>.foo()
        super<Demo2>.foo()
    }

    override fun bar() {
        super<Demo2>.bar()
    }
}

fun main(args: Array<String>) {
    val d =  Demo4()
    d.foo()
    d.bar()
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值