第七篇:Kotlin之面向对象升级(一)

上篇:Kotlin之面向对象简单

本章节来介绍Kotlin面向对象的高级部分:

一. 扩展:kotlin的扩展是一个很独特的功能,java本身支持扩展,Kotlin为了让扩展能在JVM平台上运行,必须做了一些独特的处理。

1.扩展方法:

扩展方法的语法很简单,其实就是定义一个函数,只是函数名不要写成简单的函数,而是要在函数名前添加被扩展的类(或接口)名和点号(.)。例如:

如上:程序为Raw类扩展了info()方法之后,就像为Raw类增加了info()方法一样,所有的Raw对象都可调用info()方法。不仅如此,Raw类的子类的实例也可调用info方法。

当然,扩展也可以为Kotlin系统提供类的增加方法。例如:

切记:用为指定了Int的泛型,所以只能对该泛型为Int的list集合可以调用。如果想对所有类型的泛型可以调用的话,可以不指定明确的类型。(具体泛型的使用会在接下来的泛型篇章里细讲)

实际上,Kotlin的扩展并没有真正地修改所有的扩展的类,被扩展的类还是原来的类,没有任何改变。Kotlin扩展的本质就是定义了一个函数,当程序用对象调用扩展方法时,Kotlin在编译时会执行静态解析--就是根据调用对象,方法名找到扩展函数,转换为函数调用。

介绍一下子类和父类同时有一个扩展名一样扩展,调用的时候是如何执行的,如下:

如果getName是重写的方法,执行返回的一定是son,但是因为扩展执行的是静态解析(有编译时候的类型决定,编译的类型是Base),所以调用的是Base类的getName方法,返回的是base。 

此外还有一点需要注意的是,成员的方法的优先级高于扩展的方法,所有如果成员方法和扩展方法具有同一个名字的时候,那么系统总是会执行成员方法,而不会执行扩展方法。(当然参数不同的话,就无所谓了)

也可以为可空类型扩展方法:如下:

Any这个关键字我忘记了在前面介绍没有,所在还是提上一句。 Any就是java的object,在kotlin是一切类型的父类。

2.扩展属性

Kotlin也允许扩展属性,但由于Kotlin的扩展并不是真正修改目标类,因此Koltin扩展的属性其实是通过get和set方法实现的,没有幕后字段。简单的来说,扩展的属性只能是计算属性!

kotlin的扩展属性的如下要求:

1.扩展的属性不能有初始化值(因为没有存储属性值的幕后字段)

2.不能用field关键字显示幕后字段

3.扩展只读属性必须提供getter方法,扩展读写属性必须提供getter和setter方法。

匿名扩展函数:与原来的区别在于. + 方法名,将方法名移动到前面:如下:

对于扩展在举一个最后的例子。如下:

3.const 宏的介绍

Kotlin与java的一个重大区别是:Kotlin的final修饰符不能修饰局部变量,因此open自然也不能修饰局部变量。所以Kotlin提供了宏的概念,Kotlin提供了const用来修饰可执行“宏替换”的常量。定于如下:

const的使用规则如下:

1.位于顶层或者是对象表达式的成员

2.初始化为基本类型值或者字符串类型

3.没有自定义的getter方法。

定义宏变量的时候需要注意的是:

MAX_VALUE_ONE这样的写法可以,能够得到确切的值,但是MAX_VALUE_TWO这样的写法是错误的,在编译的时候无法得到确切的值。

4.final和open

kotlin 有一个非常特别的设计:它会为非抽象类自动添加final修饰符,也会为非抽象方法,非抽象属性等无须重写的成员自动添加final修饰符。如果开发者希望取消kotlin自动添加final修饰符,可以使用open修饰符,open修饰符与final是反义词。(对于这样的设计,我个人是比较青睐的。因为一个类加上final和不加上final对于性能来说其实差距还是蛮大的,不知道原因的同学可以查阅一下。但是对于好多开发者来说,不会注意这个类加不加final,即使这个类不需要继承。所以说kotlin其实对java和java开发者来说,真的就是一种优化代码而已,方便开发高性能的代码)。

二.类的种类:

1.不可变类:不可变类的意思是创建该类的实例后,该实例的属性值是不可以改变的。其实很简单,就是对于参数加上val修饰。如下:

与可变类相比,不可变类的实例在整个生命周期中永远处于初始化状态,他的属性值不可以改变。

下面有这样一个例子:



通过这样仍然可以对address里边的属性进行改变,在语义上这样是不对的,那么如何实现彻彻底底的不可变类呢。如下:

这样写就能彻彻底底实现不可变类啦~

密封类:密封类是一种特殊的抽象类,专门用于派生子类。密封类与普通类的区别在于:密封类的子类是固定。密封类的子类必须与密封类本身在同一个文件中,在其他文件中则不能为密封类派生子类,这样就限制了在其他文件中派生子类。

上边定义了一个密封类,接下来即可在该密封类中定义抽象方法,由此可见,密封类的本质就是抽象类。有规则可以知道,密封类的所有构造器都必须是private的,不管开发者是否使用private修饰,系统都会为之自动添加private修饰。

有人会问到:那些密封类的好处是什么呢?因为密封类的子类是固定的,编译器可以清楚地知道密封类有多少个子类,所以在使用when表达式的时候,编译器可以知道是否覆盖了所有情况,从而判断是否需要添加else子句。

嵌套类和内部类:

Kotlin的嵌套类相当于java的静态内部类。而kotlin的内部类相当于java的非静态内部类。(在kotlin使用内部类的时候,用到了inner这个修饰符   inner class className {})

匿名内部类:

Java有一个非常实用的功能:匿名内部类,Kotlin则彻底抛弃了这个功能。不过同学不必担心,Kotlin提供了一个更加强大的语法:对象表达式。

对象表达式和对象声明:

对象表达式还有如下规则:

1.对象表达式不能是抽象类,因为系统在创建对象表达式时会立即创建对象。因此不允许将对象表达式定义抽象类。

2.对象表达式不能定义构造器。但对象表达式可以定义初始化块,可以通过初始化块来完成构造器需要完成的事情。

3.对象表达式可以包含内部类(有inner修饰的内部类),不能包含嵌套类。

指定零个父类型的对象表达式:

当然也可以指定多个父类型的对象表达式:

对象表达式用来代替java的匿名内部类的。那么对象声明就可以实现单例啦~什么是对象声明呢?如下:

这个就是对象声明,和对象表达式很相近。他们之前的不同在于对象声明不能定义在函数或者方法里边。

伴生对象:

在谈到对象声明的时候,还不得不说另外一个概念就是伴生对象:在类中定义的对象声明,可以用companion修饰,这样该对象就变成了伴生对象。每个类最多只能定义一个伴生对象,伴生对象相当于外部类的对象,程序可通过外部类直接访问:那么我们就来实现kotlin的单例吧~如下:


by修饰符这个是kotlin的委托,我会在接下来篇章里详细介绍。companion object {} 就完完整整的实现了单例。因为kotlin不在用static修饰符了。。那么可以用伴生对象来定义静态的常量。

如果细读的同学可以会问:你刚刚说的是伴生的修饰符 + 对象声明来实现的那么应该怎么写吧,怎么少了名字呢?

其实名字完全可以省略的,因为在调用的过程中,是当前的类名.instance, 调用变量的话是类名.DB_NAME等等,所以起不起名字都没有关系。

伴生对象扩展:

这样就可以实现对伴生对象扩展啦~~

三.接口:

接口定义的方法既可是抽象方法,也可是非抽象的方法。如果一个只读的属性没有定义getter方法,kotlin会自动为该属性添加abstract修饰符,如果一个读写属性没有定义getter和setter方法,kotlin会自动为该属性添加abstract修饰符。

Kotlin接口和java接口还有一个区别就是:Java接口中的所有成员都会自动使用public修饰符。如果要添加访问修饰符,则只能用public;如果不加修饰符,则系统默认是public。对于不需要被实现重写的成员呢,我们可以定义private或public修饰(在kotlin接口里,成员可以不必须是抽象的。方法可以定义实体)。默认的情况下是public修饰符代替。

因为本篇幅有点过长,还剩下枚举和类的委托没有介绍,打算在下一篇介绍。下篇近期会更新。如果感觉还不错的同学那么点波关注吧~~

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

推荐阅读更多精彩内容