Kotlin:主次构函数、覆盖属性和伴生对象给你带来什么

一、类


  1. Kotlin使用关键字class声明类
  2. 类的声明由类名、类头(指定参数类型、主构函数等)和由大括号包围的类体构成
  3. 类头和和类体都是可选的,如果没有类体,可以省略花括号
//1.使用关键字class声明类
class Invoice {
}
//3.类头和类体都都是可选,没有类体可以省略花括号
class Empty

二、构造函数


  1. 在Kotlin中一个类可以有一个主构造函数一个或多个次构造函数
  2. 主构造函数是类头的一部分:它跟在类名(和可选的类型参数)后。如果主构造函数没有任何注解或可见性修饰符constructor关键字可省略,否则是必须的;
  3. 主构函数不能包含任何代码,初始化代码放在以init关键字作为前缀的初始化块中
  4. 主构函数的参数可以在初始化块中使用,也可以在类体内声明的属性初始化器中使用
  5. 与普通属性一样,主构函数中声明的属性也可以是可变(var )或者只读(val )
//2.类名Customer后,主构造函数(firstName: String) ,无注解和可见性修饰符,constructor关键字省略
//5.主构函数中声明属性name是只读的
class Customer(val name: String) {
    //3.主构函数无代码,放在init关键字初始化块中
    init {
        logger.info("Customer initialized with value ${name}")
    }
    //4.主构函数参数可以类体内声明的属性初始化器中使用,或者初始化块中使用
    val customerKey = name.toUpperCase()
}

三、次构造函数


  1. 次构造函数声明前缀有constructor
  2. 如果类有一个主构造函数,每个次构造函数可以使用this关键字直接委托或者通过别的次构造函数间接委托给主构造函数
  3. 如果一个抽象类没有声明任何(主或次)构造函数,它会有一个生成的不带参数的主构造函数,可见性是public。如果不希望类有一个公有构造函数,需要声明一个带有非默认可见性的主构造函数;
class Person {
    //1.次构造函数声明前缀有constructor
    constructor(parent: Person) {
        parent.children.add(this)
    }
}
class Person(val name: String) {
    //2.使用this关键字,直接委托给主构造函数
    constructor(name: String, parent: Person) : this(name) {
        parent.children.add(this)
    }
}
//3.主动声明一个公有构造函数,“覆盖 ”没有声明任何主次构造函数默认生成的不带参数的主构造函数
class DontCreateMe private constructor () {
}

四、创建类的实例


  1. 创建类的实例,像普通函数一样调用构造函数,Kotlin中没有new关键字
  2. 类的成员包含:构造函数和初始化块,函数,属性,嵌套类和内部类,对象声明
//1.像普通函数一样调用构造函数,没有new关键字
val invoice = Invoice()
val customer = Customer("Joe Smith")

五、继承


  1. 在Kotlin中所有类都有一个共同的超类Any,没有声明超类型声明的都是默认超类Any;
  2. Any不是java.lang.Object:除了equals()、hashCode()和toString()外没有任何成员;
  3. 要声明一个显式的超类型,把类型放在类头的冒号之后
  4. 如果类有一个主构函数,其基类可以(并且必须)用(基类型的)主构函数参数就地初始化
  5. 如果没有主构函数,每个次构函数必须使用super关键字初始化其类型,或委托给一个构造函数初始化
//1.从 Any 隐式继承
class Example
//2,3.Derived继承超类Base,超类型放在类头的冒号之后
open class Base(p: Int)
//4.Base有一个主构函数,Derived必须使用Base的主构函数初始化
class Derived(p: Int) : Base(p)
//5.View没有主构函数,MyView的次构函数使用super委托给另一个构造函数;
class MyView : View {
    constructor(ctx: Context) : super(ctx)
    constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs)
}

Java对比:类上open标注与Java中final相关,它允许其它类从这个类继承。默认情况下,Kotlin所有的类都是final;

六、覆盖方法


  1. Kotlin与Java不同,需要显示使用open关键字标注可覆盖的成员使用override关键字覆盖后的成员
  2. 标记为override的成员本身是开放的,如果你想禁止再次覆盖使用final关键字
//1.open显示标注可继承的类Base,可覆盖的方法v(),否在默认为final
open class Base {
    open fun v() {}
    fun nv() {}
}
class Derived() : Base() {
    //1.override标注覆盖方法,否则编译出错
    override fun v() {}
}
open class AnotherDerived() : Base() {
     //2.final关键字禁止本身开放的override成员
     final override fun v() {}
}

七、覆盖属性


  1. 和方法覆盖类似,在超类中声明后再派生类中重新声明的属性必须以override开头,并且必须具有兼容类型;
  2. 每个声明的属性可以由具有初始化器的属性或者具有getter方法的属性覆盖;
  3. 可以使用一个var属性覆盖一个val属性,反之则不行。因为val本质声明了一个getter方法,覆盖为var只是在子类中额外声明一个setter方法
open class Foo {
    open val x: Int get() { …… }
}
//1.以override开头的x,覆盖了Foo中open开头的属性x
class Bar1 : Foo() {
    override val x: Int = ……
}

interface Foo {
    val count: Int
}
class Bar1(override val count: Int) : Foo
class Bar2 : Foo {
    //2.var属性count覆盖了val属性count,本质增加额外的setter方法
    override var count: Int = 0
}

八、调用超类实现


  1. 派生类可以使用super关键字调用超类的函数与属性访问器的实现;
  2. 在一个内部类访问外部类的超类,可以由外部类名限定的super关键字实现:super@Outer;
open class Foo {
    open fun f() { println("Foo.f()") }
    open val x: Int get() = 1
}
class Bar : Foo() {
    override fun f() {
        //1.super关键字调用超类的函数
        super.f()
        println("Bar.f()")
    }

    //1.super关键字调用属性访问器
    override val x: Int get() = super.x + 1
}

class Bar : Foo() {
    override fun f() { /* …… */ }
    override val x: Int get() = 0

    inner class Baz {
        fun g() {
            //2.调用 Foo 实现的 f()
            super@Bar.f()
            //2.使用 Foo 实现的 x 的 getter
            println(super@Bar.x)
        }
    }
}

九、覆盖规则


  1. 在Kotlin中,如果一个类从它的直接超类继承相同的成员的多个实现必须覆盖这个成员并提供自己的实现(也许用继承来的其中之一);
  2. 为了表示采用从哪个超类型继承的实现,使用尖括号中超类型名限定的super
open class A {
    open fun f() { print("A") }
    fun a() { print("a") }
}

interface B {
    // 接口成员默认就是“open”的
    fun f() { print("B") } 
    fun b() { print("b") }
}

class C() : A(), B {
    // 1、2.编译器要求覆盖 f(),分表使用限定符调用A.f()和B.f()
    override fun f() {
        super<A>.f()
        super<B>.f() 
  }
}

十、抽象类


  1. 类和其中的某些成员可以声明为abstract抽象成员在本类中可以不实现,也并不需要open标注抽象类和函数;
  2. 可以用一个抽象成员覆盖一个非抽象的开放成员
open class Base {
    open fun f() {}
}

//1.Derived类使用abstract声明为抽象类
abstract class Derived : Base() {
    //2.用一个抽象成员覆盖一个非抽象的开放成员
    override abstract fun f()
}

十一、伴生对象


Java对比:Kotlin中类没有静态方法,大多数情况下,建议简单的使用包级函数。或在类内声明一个伴生对象,就可以像Java/C#调用静态方法相同的语法来调用其它成员,只使用类名作为限定符;


1.新技术,新未来!尽在1024工场。时刻关注最前沿技术资讯,发布最棒技术博文!(甭客气!尽情的扫描或者长按!)

1024工场服务号

2.加入“Kotlin开发”QQ讨论群,一起学习一起Hi。(甭客气!尽情的扫描或者长按!)
Kotlin开发群

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

推荐阅读更多精彩内容