most from reference

Kotlin的类的声明使用关键字class

class Invoice {
}

类声明由类名、类头(指定其类型参数,构造函数等)和类体组成,由大括号括起来。如果一个类没有方法体,可以省略花括号。

class Empty

构造函数

Kotlin中类可以有一个主要的构造函数和一个或多个辅助构造函数。主构造函数是类头的一部分:它在类名后面(可选的类型参数)

class Person constructor(firstName: String) {
}

如果主构造函数没有任何注释或可见性修饰符,那么可以省略constructor关键字:

class Person(firstName: String) {
}

主构造函数不能包含任何代码。初始化代码可以放在初始化程序块中,前缀为init关键字:

class Customer(name: String) {
    init {
        logger.info("Customer initialized with value ${name}")
    }
}

请注意,初始化程序块中可以使用主构造函数的参数。他们也可以用在类体重声明的属性初始化器中:

class Customer(name: String) {
    val customerKey = name.toUpperCase()
}

实际上,为了声明属性并在主构造函数初始化,Kotlin有一个简介的语法:

class Person(val firstName: String, val lastName: String, var age: Int) {
    // ...
}

与常规属性大致相同,主构造函数中声明的属性可以是可变的(var)或只读的(val)。

如果构造函数具有注释或可见性修饰符,则构造函数的关键字是必需的,修饰符在关键字之前:

class Customer public @Inject constructor(name: String) { ... }

有关更多详细信息,请参考可见性修饰符

二级构造函数

类还可以声明辅助构造函数,它们以构造函数为前缀:

class Person {
    constructor(parent: Person) {
        parent.children.add(this)
    }
}

如果类具有主构造函数,则每个辅助构造函数需要通过另一个辅助构造函数直接或间接地委派给主构造函数。使用this关键字对同一个类的另一个构造函数进行委派:

class Person(val name: String) {
    constructor(name: String, parent: Person) : this(name) {
        parent.children.add(this)
    }
}

如果一个非抽象类没有声明任何构造函数,那么它将具有没有参数的主构造函数。构造函数的可见性将是公开的。如果你不希望您的类具有公共构造函数,则需要声明具有非默认可见的空主构造函数:

class DontCreateMe private constructor () {
}

注意:在JVM上,如果主构造函数的所有参数都具有默认值,编译器将生成一个额外的无参数构造函数,它将使用默认值。这使得更容易使用Kotlin与诸如Jackson或JPA的库,通过无参数构造函数创建类实例。

class Customer(val customerName: String = "")

创建类的实例

要创建一个类的实例,我们调用构造函数:

val invoice = Invoice()

val customer = Customer("Joe Smith")

请注意,Kotlin没有new关键字。

嵌套类描述了创建嵌套、内部和匿名内部类的实例。

类成员

类可以包含

继承

Kotlin中的所有类都有一个共同的超类Any:

class Example // Implicitly inherits from Any

Any不是java.lang.object,特别是除了equals()、hashCode()和toString(),它没有任何成员。请参考java互操作性部分。

要声明一个现实的超类,我们将冒号后面的类型放在类头中:

open class Base(p: Int)

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

如果类具有主构造函数,则可以使用主构造函数的参数(并且必须)初始化基础类型。

如果类没有主构造函数,则每个辅助构造函数必须使用super关键字初始化基类型,或者委托给另一个构造函数。请注意,在这种情况下,不同的辅助构造函数可以调用基类型的不同构造函数:

class MyView : View {
    constructor(ctx: Context) : super(ctx)

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

kotlin中的open关键字与Java中的final关键字正好相反:它允许其他人可以继承这个类。默认情况下,Kotlin中的所有类都是final, 如果要继承,则都需要加上open关键字。

复写方法

正如我们前面提到的,我们坚持在Kotlin做出明确的事情。与Java不同的是,Kotlin需要对可覆盖成员进行显式注释(open关键字):

open class Base {
    open fun v() {}
    fun nv() {}
}
class Derived() : Base() {
    override fun v() {}
}

override的关键字是必须的,如果缺少,编译器会报错。如果在函数上没有open关键字,就像Base.nv()在子类中声明具有相同签名的方法是非法的。

标记为override的成员本身是打开的,也就是说可以在子类中被覆盖。如果要禁止重新覆盖,请使用final:

open class AnotherDerived() : Base() {
    final override fun v() {}
}

复写属性

覆写属性的工作方式与覆写方法类似; 在超类上声明的然后在派生类上重新声明的属性必须加上override关键字,并且它们必须具有兼容类型。每个声明的属性可以被具有初始化器的属性或具有getter方法的属性覆盖。

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

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

您也可以用val属性覆盖var属性,反之亦然。这是允许的,因为一个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
}

调用父类的实现

派生类中的代码可以使用super关键字调用其超类函数和属性访问器实现:

open class Foo {
    open fun f() { println("Foo.f()") }
    open val x: Int get() = 1
}

class Bar : Foo() {
    override fun f() {
        super.f()
        println("Bar.f()"}
    }

    override val x: Int get() = super.x + 1
}

在内部类中,通过使用外部类名称的super关键字来完成外部类的超类super@Outer:

class Bar : Foo() {
    override fun f() { /* ... */ }
    override val x: String get() = "..."

    inner class Baz {
        fun g() {
            super@Bar.f() // Calls Foo's implementation of f()
            println(super@Bar.x) // Uses Foo's implementation of x's getter
        }
    }
}

复写规则

在Kotlin中,实现继承由以下规则控制:如果类从其直接超类继承同一成员的许多实现,则它必须覆盖该成员并提供自己的实现(可能使用其中一个继承的)。为了表示从其继承的实现的超类型,我们在尖括号中使用超类型名称超级限定,例如super:

open class A {
    open fun f() { print("A") }
    fun a() { print("a") }
}

interface B {
    fun f() { print("B") } // interface members are 'open' by default
    fun b() { print("b") }
}

class C() : A(), B {
    // The compiler requires f() to be overridden:
    override fun f() {
        super<A>.f() // call to A.f()
        super<B>.f() // call to B.f()
    }
}

它的优良来自继承A和B,我们没有问题,a()并且b()因为C继承只有一个实现每个功能的。但对于f()我们继承由两种实现方式C,因此,我们必须覆盖f()中C ,为我们自己的实现,消除了不确定性。

抽象类

一个类和其一些成员可以被声明为抽象。抽象成员在类中没有实现。请注意,我们不需要使用open关键字来注释抽象类和函数。

我们可以用抽象覆盖一个非抽象的open成员

open class Base {
    open fun f() {}
}

abstract class Derived : Base() {
    override abstract fun f()
}

伴生对象

在Kotlin中,与Java或C#不同,类没有静态方法。在大多数情况下,建议简单地使用包级别的功能。

如果需要编写一个可以调用的函数,而不需要一个类实例,但需要访问一个类的内部(例如,一个工厂方法),则可以将其作为对象声明的一个成员编写 。

更具体地说,如果您在类中声明了一个伴生对象,则可以使用与使用类名作为限定符的Java / C#中调用静态方法相同的语法来调用其成员。

Kotlin Reference (八) Classes and Objects的更多相关文章

  1. Reloading Java Classes 101: Objects, Classes and ClassLoaders Translation

    The original link: http://zeroturnaround.com/rebellabs/reloading-objects-classes-classloaders/ A Bir ...

  2. Classes as objects

    Before understanding metaclasses, you need to master classes in Python. And Python has a very peculi ...

  3. Kotlin Reference (二) Idioms

    most from reference 一些常用操作 创建单例类 object 数据类data classList.Map.Array的简单操作Lazy延迟加载属性空类型?空类型表达式?..?:.?. ...

  4. Kotlin Reference (一) Basic Syntax

    什么是Kotlin Kotlin翻译成中文叫"靠他灵",它是由JetBrains公司发明的一种基于JVM的编程语言,目前Google宣布kotlin为Android开发的官方语言. ...

  5. [REPRINT] Java 101: Classes and objects in Java

    http://www.javaworld.com/article/2979739/learn-java/java-101-classes-and-objects-in-java.html?page=3 ...

  6. Think Python - Chapter 15 - Classes and objects

    15.1 User-defined typesWe have used many of Python’s built-in types; now we are going to define a ne ...

  7. Kotlin Reference (十二) Extensions

    most from reference Kotlin与C#和Gosu类似,提供了扩展一个新功能的类,而不必继承类或使用任何类型的设计模式,如Decorator(装饰者模式).这是通过称为扩展的特殊声明 ...

  8. Kotlin Reference (十一) Visibility Modifiers

    most from reference 类,对象,接口,构造函数,函数,属性及setters具有可见性修饰符(getter总是具有和属性一样的可见性).在kotlin中油4个可视化修饰符:privat ...

  9. Kotlin Reference (十) Interfaces

    most from reference 接口 Kotlin中的接口非常类似于Java8,它们可以包含抽象方法的声明以及方法实现.与抽象类不同的是接口不能存储状态.它们可以具有属性,但这些需要是抽象的或 ...

随机推荐

  1. OpenStack与Hadoop的区别与联系

    Openstack是云操作系统,是将物理机虚拟化的云服务平台,包含各种管理组件及API.Hadoop则是“云计算”中分布式计算核心:存储与计算.但其两者面向是不同层面的.举个例子:比如现有多台底层的物 ...

  2. 【bzoj4423】[AMPPZ2013]Bytehattan(平面图转对偶图+并查集)

    题目传送门:bzoj4423 如果是普通的删边判连通性,我们可以很显然的想到把操作离线下来,倒着加边.然而,这题强 制 在 线. 虽然如此,但是题目所给的图是个平面图.那么我们把它转成对偶图试试看? ...

  3. mysql中group by存在局限性探讨(待续)

    现在有一个需求:在2018年游戏充值记录表(字段主要有: user_name , money , game_id , 表有6000w行)查找出哪些人在某段日期内累计充值金额在100~500元范围内的, ...

  4. You only look once

    计算MAP https://www.zhihu.com/question/53405779 http://tarangshah.com/blog/2018-01-27/what-is-map-unde ...

  5. MySQL事务的隔离级别

    为什么需要隔离 当多个线程都开启事务操作数据库中的数据时,数据库系统要能进行隔离操作,以保证各个线程获取数据的准确性,在介绍数据库提供的各种隔离级别之前,我们先看看如果不考虑事务的隔离性,会发生的几种 ...

  6. 最简js深浅拷贝说明

    1.浅拷贝 浅拷贝是拷贝引用,拷贝后的引用都是指向同一个对象的实例,彼此之间的操作会互相影响.  浅拷贝分两种情况: 1.直接拷贝源对象的引用 2. 源对象拷贝实例,但其属性对象(类型为Object, ...

  7. 最优化问题 Optimization Problems & 动态规划 Dynamic Programming

    2018-01-12 22:50:06 一.优化问题 优化问题用数学的角度来分析就是去求一个函数或者说方程的极大值或者极小值,通常这种优化问题是有约束条件的,所以也被称为约束优化问题. 约束优化问题( ...

  8. mysql数据库优化课程---17、mysql索引优化

    mysql数据库优化课程---17.mysql索引优化 一.总结 一句话总结:一些字段可能会使索引失效,比如like,or等 1.check表监测的使用场景是什么? 视图 视图建立在两个表上, 删除了 ...

  9. JavaScript高级与面向对象

    对象:任何事物都可以看作是对象. 1.面向对象与面向过程的概念 面向过程:凡是自己亲力亲为,自己按部就班的解决现有问题. 面向对象:自己充当一个指挥者的角色,指挥更加专业的对象帮我解决问题. 联系:面 ...

  10. sina sae搭建wordpress数据库配置

    sina app engine上搭建wordpress,使用快速安装向导会无法连接数据库. 可以在本地修改好 wp-config.php再提交. <?php /** * WordPress 基础 ...