Kotlin学习笔记(二)--面向对象编程

1. 类和对象

和java一样,Kotlin也是一门面向对象的编程语言。
下面我们通过一个简单的例子了解一下:

class Person{
	var name="Tom"
	var age=0
	 fun eat(){
	 println(name+"is eating,he is $age years old.")
	 }
}

调用:

fun main(){
	val p=Person()
	p.name="Tom"
	p.age=6
	p.eat()
}

可以看出在Kotlin中,实例化一个类和java是基本类似的,只是去掉了new关键字,之所以这么设计,是因为当你调用某个类的构造函数时,你的意图只可能是对这个类进行实例化,所以,即使没有new关键字也能清晰的表达出你的意图。

2. 继承与构造函数
2. 1 继承

在Kotlin中任何一个非抽象类默认都是不可以被继承的,相当于java中给类声明了final关键字,之所以这么设计是因为类和变量一样,最好都是不可变的,而一个类允许被继承的话,它无法预知子类会如何实现,可能就会存在一些未知的风险。但抽象类必须可以被继承,否则就没有意义
那么非抽象类如何才能被继承呢?只要在类前面加上open关键字即可。例如:

open class Person {
	...
}


class Student:Person(){
	var sno=""
	var grade=0
}

通过上述代码你会发现,Student继承的Person类后还带了一对(),和java的有些不太一样,这里就涉及到了kotlin中的主构造函数、次构造函数等方面的知识。

2. 2 主构造函数、次构造函数
2. 2.1 主构造函数

Kotlin将构造函数分成了两种:主构造函数、次构造函数。主构造函数是最常用的构造函数,每个类默认都会有一个不带参数的主构造函数,当然你也可以显式的给它指明参数。主构造函数的特点是没有函数体,直接定义在类名的后面即可。例如:

class Student(val sno:String,val grade:Int) : Person(){
}

这样在实例化Student的时候必须传入sno和grade两个参数

val Student = Student("Tom",5)

另外,由于构造函数中的参数是在创建实例的时候传入的,不像之前的写法还得重新赋值,因此我们将参数全部声明为val。
由于主构造函数中没有函数体,如果我们想在主构造函数中编写一些逻辑该怎么办呢?Kotlin给我们提供了一个 init结构体,所有主构造函数中的逻辑都可以写在里面

class Student(val sno:String,val grade:Int) : Person(){
	init {
        println(sno is $sno,grade is $grade")
    }
}

和java一样,子类中的构造函数必须调用父类中的构造函数,Kotlin也作了这样的规定。在java中子类构造函数调用父类的构造函数都是在函数体中调用的,但Kotlin的主构造函数中没有函数体,应该怎么办呢?
Kotlin是这样设计的,子类的主构造函数调用父类中的哪个构造函数,在继承的时候通过括号来指定
如果我们将Person类改造如下:

open class Person(val name:String,val age:Int) {
}

那么原来的Student类一定会报错,因为Person类中已经没有无参构造函数了,要解决这个错误,我们可以简单改造一下Student的主构造函数,以及调用的Person构造函数:

class Student(val sno:String,val grade:Int,name:String,age:Int) : Person(name,age){
}

需要注意的是,我们在Student类的主构造函数中增加name和age两个字段时,不能再将它们声明为val,因为在主构造函数中声明成val或者var的参数将自动成为该类的字段,这会导致和父类中同名的name和age字段造成冲突。所以,这里的name和age参数前不加任何关键字,让它们的作用域仅限定于主构造函数当中。

2. 2.1 次构造函数

在Kotlin中任何一个类只能有一个主构造函数,但是可以有多个次构造函数,次构造函数和主构造函数最大的不同点是它有函数体。
Kotlin中规定,当一个类既有主构造函数又有次构造函数时,所有的次构造函数都必须调用主构造函数(包括间接调用),次构造函数通过constructor 关键字来定义。

class Student(val sno:String,val grade:Int,name:String,age:Int) : Person(name,age){
	 
	 constructor(name: String,age: Int):this("",0,name,age){}
	
	//间接调用主构造函数
    constructor():this("",0){}
}

实例化:

val s1=Student("a1111",8,"Tom",16)
val s2=Student("jack",13)
val s3=Student()

接下来我们再来看一种比较特殊的情况:类中只有次构造函数,没有主构造函数。这在kotlin中是允许的。当一个类没有显式的定义主构造函数且定义了次构造函数时,它就是没有主构造函数的。例如:

class Student : Person{
	 constructor(name: String,age: Int):super(name,age){
	 }
}

注意这里发生的变化,首先Student类后面没有显式的定义主构造函数,同时又因为定义了次构造函数,所以Student类是没有主构造函数的,既然没有主构造函数,则继承Person的时候也不需要加上()了。
另外,由于没有主构造函数,次构造函数只能直接调用父类的构造函数。

3.接口

接口是用于实现多态编程的重要组成部分,我们都知道java是单继承结构的语言,任何一个类最多只能继承一个父类,但是却可以实现任意多个接口,Kotlin也是如此。下面是一个简单的接口示例:

interface Study {
    fun readBooks()
    fun doHomeWork(){//默认实现
        println("doHomeWork")
    }
}

class Student(val sno:String,val grade:Int,name:String,age:Int) : Person(name,age),Study{

	 override fun readBooks() {
        println("readBooks")
    }
}

kotlin中实现接口和继承一样,都是使用冒号,接口后面不用加上(),因为接口没有构造函数。另外,kotlin允许对接口中定义的函数进行默认实现,java在jdk1.8之后才开始支持这个功能。总的来说,接口的使用和java中的使用差别不大。

4.可见性修饰符
修 饰 符KotlinJava
public所有类可见(默认)所有类可见
private当前类可见当前类可见
protected当前类可见、子类可见当前类可见、子类、同一包路径下的类可见
default同一包路径下的类可见(默认)
internal同一模块中的类可见

通过上面的表格对比可以看出:
1.public作用一致,但kotlin中public修饰符是默认项,而在java中default才是默认项;
2.kotlin抛弃了java中default可见性,引入了internal,只对同一模块中的类可见;比如开发一个模块给别人使用,不想暴露给外部,就可以将这些函数声明为internal;

5.数据类和单例类
5. 1 数据类

Kotlin中实现一个数据类非常简单,只需要在数据类前加上data关键字即可,kotlin会根据主构造函数中的参数帮你将equals()、hashCode()、toString()等固定且无实际逻辑意义的方法自动生成,从而大大减少了开发的工作量。
另外,当一个类中没有任何代码时,还可以将尾部的大括号省略。例如:

data class Cellphone(val brand:String,val price:Double)
5. 2 单例类

在Kotlin中创建一个单例类的方式及其简单,只需要将class关键字改为object关键字即可。

object Singleton{
	fun test(){
		println("test is called")
	}
}

而调用单例类中的函数也很简单,和java中静态方法的调用方式类似(其实是kotlin在背后帮我们自动创建了一个全局唯一的Singleton实例):

Singleton.test()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值