从Java到Kotlin(三)

2018-02-27 11:29:21来源:https://www.jianshu.com/p/8e37447eadf9作者:四会歌神陈子豪人点击

分享


本篇文章主要对比Java跟Kotlin中的类和接口的写法。


目录

一、类的声明
二、构造函数
三、函数的参数
四、创建类的实例
五、数据类
六、枚举类
七、属性
八、内部类
九、可见性修饰符
十、继承
十一、接口


一、类的声明

Java声明一个类


public class Foo {}

Kotlin声明一个类


class Foo

如果只声明一个空的类,Java和Kotlin的区别还是不大的。在Kotlin中如果没有类体,Kotlin可以省略大括号{}


二、构造函数

一个类当中可以有一个主构造函数和多个次构造函数。


1.主构造函数

在Java中,如果不指定构造方法,编译器会默认生成一个不带参数的构造方法


public class User{
public User() {//默认生成
//可以在构造方法里修改代码
}
}

在Kotlin中,主构造函数是类头的一部分:它跟在类名后


class User constructor(userName: String) {
}

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


class User(userName: String) {
}

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


class User(userName: String) {
init {
//...
}
}

2.次构造函数

Java中的构造方法


public class User {
public User(String userName) {
}
//次构造函数
public User(String userName, int age) {
}
//次构造函数
public User(String userName, int age, String sex) {
}
}

Kotlin的次构造函数前面必须加constructor关键字


class User(userName: String) {
//主构造函数的实现部分
init {
println(userName)
}
//次构造函数,可通过this调主构造函数
constructor() : this("czh")
//次构造函数,可通过this调主构造函数
constructor(age: Int) : this("czh") {
println(age)
}
//次构造函数,通过this调主构造函数
constructor(sex: String, age: Int) : this("czh") {
println("$sex$age")
}
}
//实例化User
User()
User("Czh")
User(2)
User("男",22)


运行代码,得到结果:



注意:在实例初始化期间,可以有多个init代码块,按照它们出现在类体中的顺序执行,如:


    init {
println(1)
}
init {
println(3)
}
init {
println(2)
}

执行该段代码,打印顺序就是1->3->2


三、函数的参数
1.Kolin函数中的默认参数

Kotlin支持默认参数,在调用函数时不指定参数,就会使用默认参数,而Java并不支持默认参数。举个例子:


class User(userName: String = "Czh", age: Int = 22)

如果我们在实例化User的时候不传入参数,userName默认就是Czh,age默认就是22,如下所示:


var user = User()

如果在设置了默认值后,不想用默认值的话可以在创建实例时传入参数,如下所示:


var user = User("ABC" , 123)

2.Kolin函数中的命名参数

如果一个默认参数在一个无默认值的参数之前,那么该默认值只能通过使用命名参数调用该函数来使用,如下所示:


class User(userName: String = "Czh", age: Int)
var user = User(age = 22)

四、创建类的实例

Java使用关键字new创建类的实例:


new User();

Kotlin没有new关键字,所以直接创建类的实例:


User()

五、数据类

在Kotlin中,存在数据类这样一个概念,我们经常创建一些保存数据的类,并标记为 data,相当于Java中拥有Set和Get方法的实体类。下面来作个对比:
Java实体类:


public class User {
String userName;
int age;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
if (age != user.age) return false;
return userName != null ? userName.equals(user.userName) : user.userName == null;
}
@Override
public int hashCode() {
int result = userName != null ? userName.hashCode() : 0;
result = 31 * result + age;
return result;
}
@Override
public String toString() {
return "User{" +
"userName='" + userName + '/'' +
", age=" + age +
'}';
}
}

对应的Kotlin数据类:


data class User(var userName: String, var age: Int)

数据类用关键字data标识,会自动创建下面的方法:



getter/setter方法;
equals()/hashCode() 对;
toString() 格式是 "User(name=Czh, age=22)"
componentN() 函数 按声明顺序对应于所有属性;
copy() 函数。

创建数据类需要注意的是:


主构造方法至少要有一个参数,且参数必须标记为val或var
数据类不能用open、abstract、sealed(封闭类)、inner标识

获取数据类实例后,直接可以调用这些方法:



简单解释一下copy()函数。在很多情况下,我们需要复制一个对象改变它的一些属性,但其余部分保持不变。 copy() 函数就是为此而生成。举个例子:


var user = User("Czh2",22)
var user1 = user.copy(age = 23)
Toast.makeText(this, user1.toString(), Toast.LENGTH_SHORT).show()


运行代码,弹出toast:



六、枚举类

Java的枚举类跟Kotlin的枚举类非常相似。
Java定义一个枚举类


enum Color {
RED, GREEN, BLUE
}

Kotlin定义一个枚举类


enum class Color {
RED, GREEN, BLUE
}

Java为枚举类指定数值


enum Color {
RED(0xFF0000), GREEN(0x00FF00), BLUE(0x0000FF);
private Color(int rgb) {
}
}

Kotlin为枚举类指定数值


enum class Color(rgb: Int) {
RED(0xFF0000), GREEN(0x00FF00), BLUE(0x0000FF)
}

Java枚举类与Kotlin枚举类除了基本语法不同,其他都非常相似。


七、属性

Kotlin的类可以有属性。 属性可以用关键字var 声明为读写的,用关键字val声明为只读的。


1.声明属性

Java中的声明属性:


public class User {
String userName;
final String sex = "男";
}

对应的Kotlin代码:


class User {
var userName: String
val sex: String = "男"
}

2.调用属性

Java需要加上getter方法和setter方法才可以调用


new User().getSex();
new User().setUserName("Czh");

Kotlin在语法上支持属性,不用为属性定义getter和setter方法。要使用一个属性,只要用名称引用它即可。


User().sex  //getter
User().userName = "Czh" //setter

3.属性的getter与setter

虽然Kotlin在语法上支持属性,但我们仍然可以在属性中使用getter和setter。举个例子:


class User {
var name = "Czh"
var userName: String
get() = name //调用User().userName,得到结果是 Czh
set(value) {
//调用User().userName = "Czh" 把name设为 Czh
//然后再调用调用User().userName,得到结果是 Czh
name = value
}
//用val只读标识只读
val sex: String
get() = "男"//调用User().sex,得到结果是 男
}

field标识符

上面例子的User类中定义了一个name来保存属性的值,如果不想定义一个字段来保存属性的值,可以使用field标识符,如下所示:


class User {
var userName: String = "Czh"
get() = field
set(value) {
field = value
}
}

通过Kotlin提供的field标识符能够更简便地读写属性值。


八、嵌套类

嵌套类指的是在类中定义的类,如下所示:
Java中的嵌套类


class User {
int age;
static class UserName{
}
}
User.UserName user= new User.UserName();

Kotlin用inner关键字标记嵌套类


class User {
var age: Int = 0
inner class UserName {
}
}
var userName: User.UserName = User().UserName()

当我们用inner关键字标记嵌套类时,可以通过外部类的实例调用嵌套类。


九、可见性修饰符

Java中的可见性修饰符:













































可见性修饰符访问级别同类同包子类不同包
public公开
protected受保护×
default默认××
private私有×××

Kotlin中的可见性修饰符:



private ——本类内部(包含其所有成员)都可见
protected ——只在本类内部+子类中可见
public ——能见到类声明的任何客户端都可以见到其public成员
internal——能见到类声明的本模块内的任何客户端都可以见到其public成员

与Java可见性修饰符的可见性修饰符不同的是,多了一个internal,少了一个defaultinternal 意味着该成员只在相同模块内可见。更具体地说, 一个模块是编译在一起的一套 Kotlin 文件:
一个 IntelliJ IDEA 模块;
一个 Maven 项目;
一个 Gradle 源集;
一次 <kotlinc> Ant 任务执行所编译的一套文件。


十、继承
1.类的继承

Java类的继承


class UserActivity extends AppCompatActivity {}

Kotlin类的继承


class UserActivity:  AppCompatActivity()

Java跟Kotlin都是单继承的,也就是说,都只能有一个父类。不同的是,Kotlin使用冒号:继承,而且Kotlin的class默认不允许继承,如果想让类可以被继承,需要用open关键字来标识该类,如下所示:


open class Food //用open关键字来标识该类
class Fruits : Food()

2.重写方法

在Kotlin中,方法也是默认不可重写的。如果子类要重写父类中的方法,要在父类的方法前面加open关键字,然后在子类重写的方法前加override关键字,如下所示:


//父类
open class Food {
open fun banana() {}
}
//子类
class Fruits : Food(){
override fun banana() {
super.banana()
}
}

十一、接口

Java接口跟Kotlin接口都是用interface关键字声明


interface A{}
interface B{}

Java用implements实现接口


class Foods implements A, B {}

Kotlin用冒号:实现接口


class Food : A, B {}

如果Kotlin中同时存在继承类和实现接口


//继承Food类和接口AB
class Fruits: Food,A, B {}

一个类可以实现多个接口,而且接口中的属性和方法都是open的,不用另外加open标识。


接口中的方法体

Kotlin接口中的方法可以有默认方法体,有默认方法体的方法可以不重写。而Java不支持接口里的方法有方法体。举个例子:


interface UserImpl {
fun getName(): String
fun getAge(): Int{
return 22
}
}
//实现接口UserImpl,可以不重写getName()
class User :UserImpl{
override fun getName(): String {
return "Czh"
}
}

总结

本篇文章主要对比了Kotlin和Java中对于类和接口的区别,相对来说Kotlin加了一些语法糖,让代码编写更方便。


参考文献:
Kotlin语言中文站、《Kotlin程序开发入门精要》
推荐阅读:
从Java到Kotlin(一)为什么使用Kotlin
从Java到Kotlin(二)基本语法


更多精彩文章请扫描下方二维码关注微信公众号"AndroidCzh":这里将长期为您分享原创文章、Android开发经验等!
QQ交流群: 705929135












最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台