java 构造函数后面大括号_面向对象:类和构造函数

Kotlin 作为类 Java 语言,在面向对象上具有与 Java 相似的特性,但是针对不同的情况进行了不同的优化,今天我们简单介绍一下 Kotlin 中的类和构造函数。

1. 定义类和创建类的实例

Kotlin 中定义类与 Java 相同,使用 class 关键字:

class 类名[主构造函数][{

//类成员

}]

Kotlin 中的类名与 Java 相同,采用骆峰式命名法,首字母大写。

不同的是,Kotlin 中的类如果是空类,没有任何语句,则可以省略大括号(闲的)。

要创建一个类的实例,只需要调用类的构造函数,不使用 new 关键字:

val s = StringBuilder("Hello World")

val list: List = ArrayList()

2. 主构造函数

Kotlin 类的构造函数与 Java 有较大区别。首先,Kotlin 把构造函数分为 主构造函数 和 次构造函数,主构造函数写在类头中,有且只有一个;次构造函数写在类语句中,可以有多个,也可以没有。

首先,我们看一个简单的 Java 类:

public class Person {

String name;

public Person(String name) {

this.name = name;

}

}

这个类定义一个 String 类型的成员变量 name,然后定义了带有一个 String 类型参数的构造函数,这个构造函数把参数列表中的 name 赋给了成员变量 name。

用 Kotlin,我们可以这样写:

class Person constructor(name: String) {

val name: String

init {

this.name = name

}

}

首先,我们使用 class 定义了一个类 Person,然后在类头用 constructor 关键字定义带有一个 String 类型参数的主构造函数。在类体里,我们定义了一个不可变的 String 类型成员变量 name,然后使用 init 关键字定义主构造函数的行为,把主构造函数的 name 参数赋给成员变量 name。

能看到,Kotlin 类的主构造函数,参数列表定义在类声明的部分,函数体却在 init 代码块里。(莫名其妙)

这样写不够简洁呀!实际上,充分利用 Kotlin 提供的特性,我们可以把这个类缩短到一行:

class Person(val name: String)

看吧,所有冗余信息都已除去,只保留了最关键的部分。想理解这句话,我们需要知道主构造函数定义中的两个细节:如果主构造函数没有任何修饰符,则可以去掉 constructor 关键字。这样,我们的类定义就很像一个函数了:

class Person(name: String) {/*……*/}

如果想使用在主构造函数前使用修饰符,那么这个 constructor 就不能省了:

class Person private constructor() {/*……*/}

如果主构造函数中定义的参数使用 val 或者 var 修饰,则会创建与这个参数同名的成员变量,并使用传入的参数值初始化这个成员变量。简单来说,就是把“定义成员变量”和“使用构造函数传入的参数初始化成员变量”简化为一个 val 或者 var 关键字。

上面的例子中,我们在主构造方法里声明 val name: String,Kotlin 就会自动为我们添加一个名为 name 的不可变的 String 类型成员变量,然后用主构造函数传入的值初始化这个成员变量,可以直接调用。

3. 次构造函数

Java 中,一个类往往有多个不同的构造函数,它们一般有下面两种关系:参数列表由少到多,参数列表少的构造函数使用 默认值 调用参数列表多的构造函数。对于这个常见的类型,Kotlin 中使用 函数默认参数 的方法简化代码;

不同的构造方法使用不同的参数列表,相互之间存在调用关系。Kotlin 中使用 次构造函数委托 的解决方法。

首先看第一种情况,这里我们给用 Java 写的 Person 类添加一些东西:

public class Person {

long id;

String name = "";

int age = 0;

public Person(long id, String name, int age) {

this.id = id;

this.name = name;

this.age = age;

}

public Person(long id, String name) {

this.id = id;

this.name = name;

}

public Person(long id, int age) {

this.id = id;

this.age = age;

}

public Person(long id) {

this.id = id;

}

}

我们添加了两个属性,一个 long 类型的 id,一个 int 类型的 age。三个构造函数都需要传入 id 变量,name 和 age 变量的要求则是 如果没有外部传入的参数,就使用默认值。

使用 Kotlin,我们可以大大简化这一长串代码:

class Person(val id: Long, val name: String = "", val age: Int = 0)

好吧,Kotlin 又是只用一行就解决了问题……

我们重点看一下参数列表:参数列表中定义了三个参数,都使用 val 关键字修饰,说明要使用它们创建成员变量并初始化;

name 和 age 参数后面都使用 = 默认值 的方法声明了它们的默认值,在调用主构造函数的时候,如果不传入参数,就使用指定的默认值。

对于构造函数的第二种类型:使用没有关系的参数列表,但存在调用关系,Kotlin 中的处理方式是使用次构造函数委托主构造函数。我们接着改一下 Person 类:

public class Person {

long id;

String name = "";

public Person(long id) {

this.id = id;

}

public Person(String name) {

this(name.hashCode());

this.name = name;

}

}

使用 Kotlin,我们可以这样写:

class Person(val id: Long) {

var name: String = ""

constructor(name: String) : this(name.hashCode().toLong()) {

this.name = name

}

}

首先,我们在主构造函数里声明了并初始化了成员变量 id,然后在类体内使用 constructor 关键字定义一个带有一个 String 类型参数的 次构造方法,这个次构造方法先调用主构造函数,然后将参数赋给成员变量。这里有几个需要注意的地方:如果类已经有了一个主构造函数,那么所有的次构造函数都要直接或间接地委托给主构造函数。也可以先委托给其他的次构造函数,再由它们委托给主构造函数。所有的次构造函数都会先调用主构造函数,再执行自己特有的代码。写法:

constructor([参数列表]): this([参数列表]) {/*……*/}

次构造函数不能在参数列表中声明并初始化成员变量,这也是上面“name: String”前面为什么没有 val 的原因。而且因为次构造函数会改动 name 的值,所以 name 必须声明为 var。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值