Kotlin Primer·类与对象(上)

前面三章的内容是写给希望快速了解 Kotlin 语言的大忙人的。 而从本章开始,才会真正讲述 Kotlin 语言的神奇之处。

与 Java 相同,Kotlin 声明类的关键字是class。类声明由类名、类头和类体构成。 其中类头类体都是可选的; 如果一个类没有类体,那么花括号也是可以省略的。

4.1 构造函数

Kotlin 的构造函数可以写在类头中,跟在类名后面,如果有注解还需要加上关键字constructor。这种写法声明的构造函数,我们称之为主构造函数。例如下面我们为Person创建带一个String类型参数的构造函数。

class Person(private val name: String) {
    fun sayHello() {
        println("hello $name")
    }
}

在构造函数中声明的参数,它们默认属于类的公有字段,可以直接使用,如果你不希望别的类访问到这个变量,可以用private修饰。 在主构造函数中不能有任何代码实现,如果有额外的代码需要在构造方法中执行,你需要放到init代码块中执行。同时,在本示例中由于需要更改 name 参数的值,我们将 val 改为 var,表明 name 参数是一个可改变的参数。

class Person(private var name: String) {
    
     init {
        name = "Zhang Tao"
    }

    internal fun sayHello() {
        println("hello $name")
    }
}

如果一个非抽象类没有声明任何(主或次)构造函数,它会有一个生成的不带参数的主构造函数。构造函数的可见性是 public。如果你不希望你的类 有一个公有构造函数,你需要声明一个带有非默认可见性的空的主构造函数。 另外,在 JVM 上,如果主构造函数的所有的参数都有默认值,编译器会生成一个额外的无参构造函数,它将使用默认值。

4.2 次级构造函数

一个类当然会有多个构造函数的可能,只有主构造函数可以写在类头中,其他的次级构造函数(Secondary Constructors)就需要写在类体中了。

class Person(private var name: String) {

    private var description:String? = null
    
    init {
        name = "Zhang Tao"
    }

    constructor(name: String, description: String) : this(name) {
        this.description = description
    }
    
    internal fun sayHello() {
        println("hello $name")
    }
}

这里我们让次级构造函数调用了主构造函数,完成 name 的赋值。由于次级构造函数不能直接将参数转换为字段,所以需要手动声明一个 description 字段,并为 description 字段赋值。

4.3 修饰符

点开 IDEA,工程目录中的 out 列表,看到我们写完的 Person被编译为 class 文件后的样子。

4.3.1 open 修饰符

Kotlin 默认会为每个变量和方法添加 final 修饰符。这么做的目的是为了程序运行的性能,其实在 Java 程序中,你也应该尽可能为每个类添加final 修饰符( 见 Effective Java 第四章 17 条)。 为每个类加了final也就是说,在 Kotlin 中默认每个类都是不可被继承的。如果你确定这个类是会被继承的,那么你需要给这个类添加 open 修饰符。

4.3.2 internal 修饰符

写过 Java 的同学一定知道,Java 有三种访问修饰符,public/private/protected,还有一个默认的包级别访问权限没有修饰符。 在 Kotlin 中,默认的访问权限是 public。而多增加了一种访问修饰符叫 internal。它是模块级别的访问权限。 何为模块(module),我们称被一起编译的一系列 Kotlin 文件为一个模块。在 IEDA 中可以很明确的看到一个 module 就是一个模块,当跨 module 的时候就无法访问另一个moduleinternal 变量或方法。

4.4 一些特殊的类

4.4.1 枚举类

在 Kotlin 中,每个枚举常量都是一个对象。枚举常量用逗号分隔。 例如我们写一个枚举类 Programer。

enum class Programer {
    JAVA, KOTLIN, C, CPP, ANDROID;
}

当它被编译成 class 后,将转为如下代码实际就是一个私有了构造函数的kotlin.Enum继承类。

public final enum class Programer 
private constructor() : kotlin.Enum<Programer> {
    JAVA, KOTLIN, C, CPP, ANDROID;
}

接着我们再来看kotlin.Enum这个类(节选)

public abstract class Enum<E : Enum<E>>
(name: String, ordinal: Int): Comparable<E> {
    companion object {}

    /**
     * Returns the name of this enum constant,
     *  exactly as declared in its enum declaration.
     */
    public final val name: String

    /**
     * Returns the ordinal of this enumeration 
     * constant (its position in its enum 
     * declaration, where the initial constant
     * is assigned an ordinal of zero).
     */
    public final val ordinal: Int

    public override final fun compareTo(other: E): Int
}

发现,其实在 Kotlin 中,枚举的本质是一个实现了Comparable的 class,其排序就是按照字段在枚举类中定义的顺序来的。

4.4.2 sealed 密封类

sealed 修饰的类称为密封类,用来表示受限的类层次结构。例如当一个值为有限集中的 类型、而不能有任何其他类型时。在某种意义上,他们是枚举类的扩展:枚举类型的值集合也是受限的,但每个枚举常量只存在一个实例,而密封类的一个子类可以有可包含状态的多个实例。

4.4.3 data 数据类

data 修饰的类称之为数据类。它通常用在我们写的一些 POJO 类上。 当 data 修饰后,会自动将所有成员用operator声明,即为这些成员生成类似 Java 的 getter/setter 方法。

本章就先介绍到这,下一章我们讲继承与组合,伪多继承与接口等内容。

原文发布于微信公众号 - Android群英传(android_heroes)

原文发表时间:2017-02-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java爬坑系列

【Java入门提高篇】Day13 Java中的反射机制

  前一段时间一直忙,所以没什么时间写博客,拖了这么久,也该更新更新了。最近看到各种知识付费的推出,感觉是好事,也是坏事,好事是对知识沉淀的认可与推动,坏事是感...

3709
来自专栏C/C++基础

C++中的临时对象

C++中临时对象(Temporary Object)又称无名对象。临时对象主要出现在如下场景。

821
来自专栏维C果糖

Guava 指南 之「使用和避免 null」

使用和避免null “null,糟糕透啦!” —— Doug Lea. “我称null为百亿美金的错误!” —— C. A. R. Hoare. 轻...

2117
来自专栏Jimoer

Java设计模式学习记录-原型模式

1445
来自专栏青玉伏案

窥探Swift之需要注意的基本运算符和高级运算符

  之前更新了一段时间有关Swift语言的博客,连续更新了有6、7篇的样子。期间间更新了一些iOS开发中SQLite、CollectionViewControl...

1975
来自专栏钟绍威的专栏

Properties+重温Map+本地计数器Map方法Properties的方法用Properties的好处

昨天想写一个记账本,发现并不能把项目名称与内容关联起来,于是乎我想到了map,可是又不知道map储存到文件中又怎么读出来,幸好今天遇到了properties ...

2027
来自专栏诸葛青云的专栏

C语言位运算的妙用你知道多少?

位运算在驱动开发中是经常遇到的,尤其是置0和置1。既要指定的位数发生变化,又不能改变其它位的值,还要高效率的编写代码,这时候技巧就很重要了。在位运算中有几个符号...

1674
来自专栏一个会写诗的程序员的博客

写了多年的Java,直到看到Kotlin,原来代码可以如此优雅!

如果你是像我一样是一名 优秀 的Java开发者 _ ,而且已经想用kotlin来实现你的程序,那么,抱歉!不要用Java的语法思维来写Kotlin,不要让kot...

3294
来自专栏偏前端工程师的驿站

(cljs/run-at (->JSVM :browser) "语言基础")

前言  两年多前知道cljs的存在时十分兴奋,但因为工作中根本用不上,国内也没有专门的职位于是搁置了对其的探索。而近一两年来又刮起了函数式编程的风潮,恰逢有幸主...

2217
来自专栏Android开发指南

Effecvtive Java Note

3055

扫码关注云+社区

领取腾讯云代金券