类声明

和Java一样,Kotlin中使用关键字class来声明一个类。如下即是声明一个最简单的没有任何属性和方法的类

// 没有任何属性、方法的Invoice 类
class Invoice {}

一个完整的类声明包含类名类头(指定构造参数、构造方法等),类体(用大括号包裹的部分)。类头和类体这两个部分并非必要的,类头和类体都是可选的; 如果一个类没有类体,可以省略花括号。

class Invoice

构造函数

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

class Person constructor(firstName: String) {
}

如果主构造函数没有任何注解或者可见性修饰符,可以省略这个 constructor 关键字。

class Person(firstName: String) {
}

主构造函数不能包含任何的代码。初始化的代码可以放到以 init 关键字作为前缀的初始化块(initializer blocks)中:


class Customer(p : Int) {
init {
println("Customer类初始化")
}
}

次构造函数

二级构造函数,也称为次级构造函数。关于二级构造函数,主要有以下几点:

  1. 次级构造函数不能省略constructor关键字
  2. 当类拥有主构造函数时,任何一个二级构造函数都需要直接或间接通过另一个二级构造函数代理主构造函数
  3. 类中的一个构造函数代理另一个构造函数,需要使用关键字this

类也可以声明前缀有 constructor次构造函数

class Person {
constructor(parent: Person) {
parent.children.add(this )
}
}
class Person constructor(id: Int) {//(构造函数No.0)主构造函数
var id = id//主构造函数初始化id
var name = ""
var age = 0
//(构造函数No.1)直接代理主构造函数
constructor(name: String, id: Int) : this(id) {
this.name = name
}
//(构造函数No.2)代理了构造函数No.1,间接代理主构造函数
constructor(name: String, age: Int, id: Int) : this(name, id) {
this.age = age
}
}

继承

和所有的Java类都有一个共同的父类Object一样且不支持同时继承多个父类。Kotlin中所有的类都拥有一个共同的父类Any(但Any不是Object,不要搞错)。Any相比Object其内部结构要简单很多,仅有equals()、hashCode()、toString()三个抽象方法。

//默认情况下,在 Kotlin 中所有的类都是 final,
//抽象是面向对象编程的特征之一,类本身,或类中的部分成员,都可以声明为abstract的。抽象成员在类中不存在具体的实现。 open class Base(p: Int){
init {
println("基类")
} //重写
//在基类中,使用fun声明函数时,此函数默认为final修饰,不能被子类重写。
// 如果允许子类重写该函数,那么就要手动添加 open 修饰它, 子类重写方法使用 override 关键词:
open fun sdutent() {
println("基类方法")
}
}
class Customer(p : Int): Base(p) {

    init {
println("Customer类")
} constructor(p: Int,n: String):this(p){
println("$p is n= $n")
} override fun sdutent() {
super.sdutent()
println("重写基类的方法")
}
}

属性和赋值

在声明一个最简单的空壳类之后,我们来为它增加一些类属性。Kotlin中类的属性可以用var或者val关键字进行声明,其中var为可变属性,val为只读属性(相当于Java的final)。


class Student {
var name = "名字" //名字属性可变,用var
val birthday = "1994-10-26" //生日属性不可变,用val
}

像上面这样就简单的为Student类声明了name和birthday两个属性,且在声明属性时进行了初始化,按照Kotlin的类型推断特点,name和birthday就是属于String类型(不知道类型推断的同学可以翻阅前面的写的文章)。现在我想为Student类添加一个age属性,但是我并不想在声明时进行初始化,用Java写起来非常简单即可实现

public class JavaStudent {
private String name = "名字";
private String birthday = "1994-10-26";
private int age;//Java版的实现
}

按照Java的实现套路直接套入Kotlin你会发现IDE直接报错并提示property must be initialized or be abstract

  

按照提示我们必须把类和字段都声明为abstract才可以通过编译。
abstract class Student {
var name = "名字" //名字属性可变,用var
val birthday = "1994-10-26" //生日属性不可变,用val
abstract var age: Int
}

这样未免太过麻烦,而且理解起来也非常奇怪。Kotlin提供了延迟初始化的方式来解决初始化的问题,使用关键字lateinit即可,这样就无需声明abstract了。

可惜使用lateinit延迟初始化age之后,IDE依旧报错,这次提示的内容是lateinit modifier is not allowed on primitive type properties。Kotlin并不支持对原生类型进行lateinit,为什么呢?因为Kotlin会使用null来对每一个用lateinit修饰的属性做初始化,而基础类型是没有null类型,所以无法使用lateinit。这点很好理解,就像可以把int型变量赋值为0,却无法赋值为null一样。所以这里为了通过IDE的编译,我们可以采用两种方案,要么还是直接在age声明时进行初始化,要么不用基础类型来定义age。


class Student {
var name = "名字" //名字属性可变,用var
val birthday = "1994-10-26" //生日属性不可变,用val
var age = 0 //直接使用0初始化age,age为Int型
lateinit var ageStr: String //String不是基础类型,可以使用lateinit初始化
}

创建对象

调用类的构造器,调用方式和使用普通函数一样:

val person = Student ()

注意:Kotlin 没有 new 关键字。

 

Kotlin------类和对象(一)的更多相关文章

  1. Kotlin 类和对象

    类定义 Kotlin 类可以包含:构造函数和初始化代码块.函数.属性.内部类.对象声明. Kotlin 中使用关键字 class 声明类,后面紧跟类名: class Runoob { // 类名为 R ...

  2. Kotlin语法(类和对象)

    二.类和对象: 1. 类定义: 类的声明包含类名,类头(指定类型参数,主构造函数等等),以及类主体,用大括号包裹.类头和类体是可选的:如果没有类体可以省略大括号. class Invoice{ } 2 ...

  3. Kotlin基础(三)类、对象和接口

    类.对象和接口 一.定义类的继承结构 一)Kotlin中的接口 Kotlin的接口与Java8中相似,它们可以包含抽象方法的定义以及非抽象方法的实现,但它们不能包含任何状态. interface Cl ...

  4. 类和对象在JVM中是如何存储的,竟然有一半人回答不上来!

    前言 这篇博客主要来说说类与对象在JVM中是如何存储的,由于JVM是个非常庞大的课题,所以我会把他分成很多章节来细细阐述,具体的数量还没有决定,当然这不重要,重点在于是否可以在文章中学到东西,是否对J ...

  5. Kotlin类:功能更强、而更简洁(KAD 03)

    作者:Antonio Leiva 时间:Dec 7, 2016 原文链接:http://antonioleiva.com/classes-kotlin/ Kotlin类尽可能简单,这样用较少的代码完成 ...

  6. Java编程里的类和对象

    像我们搞计算机这块的,都知道这么一件事,当前的计算机编程语言主要分为两大块,一为面向过程,二为面向对象.Java就是一门纯面向对象的语言.学习了一个月左右的Java,在下对于Java当中的类和对象有了 ...

  7. Python - 类与对象的方法

    类与对象的方法

  8. C++基础知识(5)---类和对象

    终于把C++中的基础在前面的几篇博客中总结完了,可能还有一些语法还没有总结到,没关系,以后用到了再查资料就好.类是C++中的一个非常重要的概念,这是区别你使用的C++到底是面向过程还是面向对象的一个重 ...

  9. 简述JavaScript对象、数组对象与类数组对象

    问题引出 在上图给出的文档中,用JavaScript获取那个a标签,要用什么办法呢?相信第一反应一定是使用document.getElementsByTagName('a')[0]来获取.同样的,在使 ...

  10. 前端学PHP之面向对象系列第一篇——类和对象

    × 目录 [1]类 [2]成员属性[3]成员方法[4]对象[5]成员访问[6]this 前面的话 面向对象程序设计(OOP)是一种计算机编程架构.计算机程序由单个能够起到子程序作用的单元或对象组成,为 ...

随机推荐

  1. Angular 回到顶部 滚动到特定的页面位置

    $timeout(function() { // $location.hash('bottom'); // $anchorScroll(); // var a=angular.element(&quo ...

  2. shiro的/favicon.ico问题

    登录成功之后跳转/favicon.ico问题. 1.spring-shrio.xml里面配置加上 /favicon.ico = anon 2.web.xml中配置中加上: <mime-mappi ...

  3. PAT 1115 Counting Nodes in a BST[构建BST]

    1115 Counting Nodes in a BST(30 分) A Binary Search Tree (BST) is recursively defined as a binary tre ...

  4. execute sp_executesql 用变量获取返回值

    execute sp_executesql 用变量获取返回值 1,EXEC的使用 2,sp_executesql的使用 MSSQL为我们提供了两种动态执行SQL语句的命令,分别是EXEC和sp_exe ...

  5. VS和IE或者360兼容模式简单调试js方法

    首先IE(8.0版本以上)将脚本调试去掉,如下图 之后在vs里面的js要调试的地方添加代码debugger ,如下图所示 当程序运行到debugger处时,就会提示要调试,选择vs版本即可 之后会出现 ...

  6. BZOJ 5427: 最长上升子序列

    $f[i] 表示长度为i的最长上升子序列的最后一位的最小值是多少$ 对于普通的$LIS我们可以二分确定位置去更新$ 再来考虑对于这个,如果有某一位没有确定的话 那么这一位是可以随便取的,也就是说,所有 ...

  7. javascript 理解对象--- 定义多个属性和读取属性的特性

    一 定义多个属性 ECMAScript5 定义了一个Object.defineProperties()方法,用于定义多个属性.此方法接受两个对象参数: 第一个对象:要添加或修改其属性的对象 第二个对象 ...

  8. 转载:逻辑回归的python实现

    转载自:http://blog.csdn.net/zouxy09/article/details/20319673 一.逻辑回归(LogisticRegression) Logistic regres ...

  9. $如何用Python装饰器实现一个代码计时器?

    有时候我们很希望看到程序中某个函数或某个代码段的耗时情况,那么该如何办呢?本文用两种方式实现了代码计时器的功能,第一种方式是采用装饰器来实现,第二种方式采用上下文管理器实现. 其实计算代码的运行时间, ...

  10. PHP开发之apache mac上配置

    我使用的Mac OS X版本是10.8.2,Mac自带了Apache环境. 启动Apache 设置虚拟主机 启动Apache 打开“终端(terminal)”,输入 sudo apachectl -v ...