kotlin学习第三天

运算符重载

kotlin中每一个运算符对应一个方法。比如我们想把两个对象加起来的话,只需要把“+”对应的方法复写就可以实现了。运算符对应的方法可以通过kotlin官网http://kotlinlang.org/docs/reference查询。

fun main(args: Array<String>) {
    val p1 = Person()
    val p2 = Person()
    p1.age = 10
    p2.age = 20
    //求p1和p2的年龄和
    var plus = p1.plus(p2)
    println(plus)
}
//重写“+”方法
class Person {
    var name = "张三"
    var age = 0

    fun plus(person: Person): Int {
        return age + person.age
    }
}

类的成员

类成员可以访问并且修改,kotlin的类成员变量默认已经实现了get以及set方法。

成员的访问与修改

由于kotlin的类成员变量默认实现get以及set方法,所以类中的成员可以直接调用:

fun main(args: Array<String>) {
    val stu = Student()
    println(stu.age)
    println(stu.name)
}

class Student {
    val name = "张三"
    val age = 15
}

修改类成员的可见性

在Kotlin中,若是想要类成员对于外界只能访问不能修改,则在类成员后中写入 private set。若想类成员对外界既不能访问也不能修改,则在类成员前写入private:

class Student {
    var name = "张三"
    private set//外界无法修改name
    private var age = 15//外界无法访问、修改age
}

自定义访问器

在我们的例子中,学生的年龄不可能随意设置,比如学生是-1岁,所以需要对设置的数据进行判定,符合一定要求后才能修改。对于此类要求,我们可以用自定义访问器field:

fun main(args: Array<String>) {
    var person = Student()
    println(person.age)//20
    person.age = 35//由于35>30,所以设置失败
    println(person.age)//20

}

class Student {
    var name = "张三"
    var age = 20
        set(value) {//value对应传递的age值
            if (value > 18 && value < 30) {
                //可以通过field表示这个字段
                field = value
            }
        }
}

主构函数和次构函数

主构函数

kotlin中主构函数即构造函数,但是无法直接访问构造函数中的元素。如果想要在构造函数里面实现一些操作,需要把代码写在init里:

fun main(args: Array<String>) {
    val p1 = Person("张三", 23)
    val p2 = Person("李四", 25)
    val p3 = Person("王五", 40)
    println(p1.age)//23
    println(p2.age)//25
    println(p3.age)//40
}

class Person(name: String, age: Int) {
    var name = ""
    var age = 0

    init {
        this.age = age
        this.name = name
    }
}

var和val在主构函数参数中的作用

主构函数参数使用var和val,相当于帮我们定义了字段,参数可以直接使用。参数没有var和val修饰,参数在其他地方不能使用 。参数有var修饰,可以使用,也可以修改 。参数有val修饰,只能使用,不能修改 :

fun main(args: Array<String>) {
    val p1 = Person("张三", 23)
    val p2 = Person("李四", 25)
    val p3 = Person("王五", 40)
    println(p1.age)
    println(p2.age)
    println(p3.age)
}

class Person(val name: String,val age: Int)

次构函数

次构函数必须要调用主构函数,必须要把参数传递给主构函数,且需要用constructor关键字:

class Person2(val name: String,val age: Int){
    constructor(name: String, age: Int,phone:String):this (name,age)//调用主构函数将参数传递给主构函数
}

次构函数间调用

次构函数可以直接调用主构函数,也可以通过调用次构函数来间接调用主构函数:

class Person3(name:String,age: Int){
    //调用主构函数
    constructor(name:String,age: Int,phone: String):this(name,age)
    //通过调用次构函数来间接调用主构函数
    constructor(name:String,age: Int,phone: String,qq:String):this(name,age,phone)
}

次构函数参数使用

构造函数加var和val只能在主构函数里面加,次构函数中不能加。主构函数参数可以直接加上var和val使用,次构函数只能够自己定义变量进行保存。

class Person3(val name:String,val age: Int){
    var phone = ""
    var qq = ""
    constructor(name:String,age: Int,phone: String):this(name,age)
    constructor(name:String,age: Int,phone: String,qq:String):this(name,age,phone){
        this.phone = phone
        this.qq = qq
    }
}

继承

继承是指一个对象直接使用另一对象的属性和方法。kotlin的继承和java中的继承大体相同,但需要注意以下几点:

1.需要将父类加上open关键字

2.需要加上():

kotlin的成员函数和成员变量对应的get以及set方法都有final修饰,不能进行继承,所以要在成员函数和成员变量前加上open关键字才能进行复写:

open class father() {
    open var name = "小头爸爸"
    open var age = 40
    open fun sayHello() {
        println("老哥 早上好")
    }

}

class son : father() {
    override var name: String = "大头儿子"
    override var age: Int = 14
    override fun sayHello() {
        println("同学 早上好")
    }

}

构造函数的继承

构造函数的继承除了通常的操作外,子类也需要构造函数,并且应能在父类中找到对应的字段,还需将函数传给父类。子类也可以用父类的字段:

fun main(args: Array<String>) {
    var p = Person("张三", 30)
    var s = Student("李四", 20, "男")
    println(p.age)//30
    println(s.sex)//男
    println(s.name)//李四

}

open class Person(var name: String, var age: Int) {
    open fun morning() {
        println("早上好")
    }
}

class Student(name: String, age: Int, var sex: String) : Person(name, age) {
    override fun morning() {
        println("晚上好")
    }
}

抽象类和抽象方法

父类中的方法,被它的子类们重写,子类各自的实现都不尽相同。那么父类的方法声明和方法主体,只有声明还有意义,而方法主体则没有存在的意义了。我们把没有方法主体的方法称为抽象方法。包含抽象方法的类就是抽象类。抽象类不需要open关键字就可以被调用。

//人类 (抽象类)
abstract class Human {
    abstract var color: String
    abstract var language: String
    abstract fun eat()
}

//具体实现类
class Chinese : Human() {
    override var color: String = "yellow"
    override var language: String = "chinese"

    override fun eat() {
        println("用筷子吃饭")
    }
}

class USHuman : Human() {
    override var color: String = "white"
    override var language: String = "english"

    override fun eat() {
        println("用刀叉吃饭")
    }
}

class AfHuman : Human() {
    override var color: String = "black"
    override var language: String = "葡萄牙语"

    override fun eat() {
        println("用手吃饭")
    }
}

接口

接口的实现是在括号后面加个冒号,然后写上要实现的接口,不需要写interface。若是多个接口,就用逗号“,”隔开。

class men() : bike {
    override fun rideBike() {
        println("人骑车")
    }

}

interface bike {
    fun rideBike()
}

注意事项

1.java中接口中的字段一定要被赋值,但是Kotlin接口里的字段不能被赋值

2.java接口里面方法不能实现,kotlin可以实现

class men() : Bike, Drive {
    override val license: String = "123456"
    override fun drive() {
        println("人开车")
    }
    override fun rideBike() {
        println("人骑车")
    }

}

interface Bike {
    fun rideBike()
}

interface Drive {
    val license: String
    fun drive() {
        println("放手刹,踩油门,走")
    }
}

多态

同种功能的不同表现形式。kotlin中的多态原理同java:

abstract class Animal {
    abstract var name: String

    open fun bark() {
        println("动物叫")
    }
}

class Dog : Animal() {
    override var name: String = "旺财"

    override fun bark() {
        println("旺财  汪汪叫")
    }
}

class Cat : Animal() {
    override var name: String = "汤姆"

    override fun bark() {
        println("汤姆  喵喵叫")
    }
}

智能类型转换

在多态中,多个子类可能均与父类有差别。kotlin中可以通过智能类型推断来判断调用的字段所属于的子类,最终调用所属子类的方法。将父类引用转为子类引用,转换之前还需要判断是否是当前子类类型。一旦判断出是这个类型之后,编译器就把类型转换过去了,不需要手动转换。

fun main(args: Array<String>) {
    val shepHerdDog: Dog = ShepHerdDog()//将父类引用转为子类引用
    //判断是否是当前子类类型
    if (!(shepHerdDog is ShepHerdDog)) return
    //编译器自动转换
    shepHerdDog.shepHerd()
}

abstract class Dog

class ShepHerdDog : Dog() {
    fun shepHerd() {
        println("牧羊犬开始放羊了...")
    }
}

嵌套类、内部类

嵌套类默认都是static修饰的,属于静态类,不依赖于外部的环境,即和外部类没有关系:

fun main(args: Array<String>) {
    val inClass = outClass()
}

class outClass {
    var name: String = "李四"

    class inClass {
        fun say() {
            println(name)
        }
    }
}

内部类需要通过Inner修饰,且需要先创建出来外部环境:

fun main(args: Array<String>) {
    val inClass = outClass.inClass()
}

class outClass {
    var name: String = "李四"
    inner class inClass {
        fun say() {
            println(name)
        }
    }
}

内部类中使用this

如上例,若内部类中也有一个var name = "张三",则默认情况下会打印张三,即从最近开始找。如果我们想访问外部类中的name,也就是李四。这时候就需要把打印内容改为外部类名.this.namethis@outClass.name:

class OutClass {
    var name = "李四"

    inner class InClass {
        var name = "张三"
        fun sayHello() {
            println(this@OutClass.name)
            //或
            println(OutClass.this.name)
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343