Kotlin面向对象知识点讲解
z啵唧啵唧 人气:0类和对象
创建一个Person类
open class Person { /** * 姓名 */ var name = "" /** * 年龄 */ var age = 0 /** * 人的吃饭方法 */ fun eat() { print(name + " is eating. He is" + age +"years old.") } }
在main函数中创建Person对象,对字符进行赋值,调用类中的方法
fun main() { val p = Person(); p.name = "张三" p.age = 10 p.eat() }
注意在Kotlin当中创建对象不需要new关键字
继承和构造函数
- 继承是面向对象的一大特性
- 在Kotlin中和java不同的是,在Koitlin中任何一个非抽象类都是默认不可以被继承的,就相当于在java中给一个类加上了final关键字
- 因为在一本名为Effective Java中的书明确提到,如果一个类不是专门为了继承而设计的,那么他就应该加上final声明,禁止它可以被继承,这个属于就是编程规范了
- 在Kotlin当中的抽象类和java并没有什么区别
- 在Kotlin中如果想要一个类可以被继承,只需要在这个类的前面加上open关键字即可
- 如果一个类要继承一个类的话,在java当中使用的是extends关键字,在Kotlin当中使用的是 : 这个关键字,而且父类不仅仅要写出类名还要带上一对括号
class Student : Person() { var sno = "" var grade = 0 }
Kotlin中类的主构造函数
每个类都会默认有一个不带参数的主构造函数,但是我们也可以显示的给他指定参数,主构造函数的特点是没有函数体,直接定义在类名的后面即可
class Student(val sno: String, val grade: Int) { }
上面这行代码就表示Student的主构造函数有两个参数,分别是sno和grade
在主构造函数当中没有函数体,那么我们想要在主构造函数当中编写一些代码逻辑也是可以的,我们可以通过init结构体来进行实现
class Student(val sno: String, val grade: Int) { init { println("sno is " + sno) println("grade is" + grade) } }
通过init结构体就可以扩展的为主构造函数执行一些代码逻辑
那么子类在继承父类的时候,为什么父类名后面要跟上一对括号呢,原因是,子类在继承父类的时候,子类的构造函数必须调用父类的构造函数,所以子类的主构造函数调用父类的那个构造函数,就是由这个()来进行指定的.
class Student : Person() { var sno = "" var grade = 0 }
在这里Person类后面一对空括号表示Student类的主构造函数在初始化的时候会调用Person类的无参构造函数
次构造函数:在Kotlin当中,每一个类只能有一个主构造函数,但是可以有多个次构造函数,次构造函数也可以实例化一个类,区别就是主构造函数没有函数体,次构造函数有函数体
Kotlin规定,在一个类当中如果同时存在主构造函数和次构造函数的时候,所有的次构造函数必须调用主构造函数(包含间接调用)
次构造函数通过construtor关键字来进行声明
class Student(val sno: String, val grade: Int, name: String, age: Int) : Person(name, age) { //次构造函数1:直接调用本类的主构造函数,这个次构造函数有两个参数分别是nanem和age,然后他在调用本类的主构造函数的时候直接实例化了主构造函数中的sno和grade两个参数,然后将自己的name和age传给了调用了的主构造函数 constructor(name: String, age: Int) : this("", 0, name, age){ } //次构造函数2:不接收任何的参数,然后没有直接调用本类的主构造函数,而是调用了次构造函数1,相当于间接调用了本类的主构造函数 constructor() : this("张三", 18) }
当Student类通过上述方式编写之后,我们就可以使用主构造函数或者此构造函数对其进行实例化了,那么对Student类进行实例化的方式就有了三种
//使用主构造函数对Student类进行实例化 val student1 = Student("123", 1, "张三", 18) //使用次构造函数1对Student进行实例化 val student2 = Student("张三", 18) //使用次构造函数2对Student进行实例化 val student3 = Student()
还有一种比较特殊的情况,类中只包含次构造函数,没有主构造函数,这种情况虽然少见,但是在Kotlin当中是允许的,当一个类没有显示的定义主构造函数但是定义了次构造函数的时候,它就是没有主构造函数的
class Student : Preson { constructor(name: String, age: Int) : super(name, age) { } }
在上面的代码中,首先Student类后i按没有显示的定义主构造函数,同时又定义了次构造函数,所以Student类是没有主构造函数的,因为没有主构造函数,所以就不牵扯子类的主构造函数调用父类的主构造函数这一说,所以说Person类的后面没有加()
另外,由于没有主构造函数,此构造函数只能直接调用父类的构造函数,所以在次构造函数在调用方法的时候将this关键字换成了super关键字
接口
Kotlin当中的接口和java当中的接口几乎完全是一致的,接口是用于多态编程的重要组成部分,java是单继承语言,但是可以实现多个接口,Kotlin中也同样是这样
定义一Study接口
interface Study { fun readBooks() fun doHomeWork() }
Student实现Study接口
class Student : Person(), Study{ var sno = "" var grade = 0 override fun readBooks() { println("读书") } override fun doHomeWork() { println("做作业") } }
在java当中继承使用的关键字是extends,实现使用的是impls关键字,而在Kotlin当中继承和实现统一使用的是 : ,如果即做了继承又进行了实现,使用,进行隔开
在上面的代码中,Student实现了Study接口,那么他就必须要实现Study中的两个方法,在Kotlin当中使用override关键字来重写父类或者实现接口中的方法.
多态编程的特性
fun main() { val student = Student() doStudy(student) } fun doStudy(study: Study) { study.readBooks() study.doHomeWork() }
因为Student实现了Study接口,在doStudy方法中,需要传递的参数是Study类型,所以也可以传递一个Student的实例
还有一点就是在Kotlin当中可以对接口中的抽象方法进行默认的实现
interface Study { fun readBooks() //在Kotlin的接口中可以对方法进行默认实现 fun doHomeWork() { println("do homework") } }
如果接口中的一个函数,拥有了函数体,这个函数中的内容就是他的默认实现,现在一个类去实现Study接口的时候,只会强制要求实现readBooks方法,而doHomeWork方法可以自由选择进行实现,不是先是就会自动使用默认的实现逻辑
访问修饰符
在java当中的访问控制符一种有四种:public,private,protected,defaule(什么都不写)
在Kotlin当中也有四种访问控制符:public,private,protected和internal,需要使用那种修饰符号的时候直接在fun关键字前面进行添加即可
private修饰符在java和Kotlin当中的作用是一摸一样的,都表示对当前类的内部进行可见
public修饰符作用虽然也是一致的,表示对所有的类都可见,但是在java中default是默认项,但是在Kotlin当中public才是默认项
protected关键字在java中表示在该类和该类的子类以及同一包中可见,但是在Kotlin当中值表示对该类和子类可见
Kotlin当中抛弃了java中的defualt权限(同一个包路径下可见)而是引入了一种新的权限internal
internal表示在同一个模块中的类可见.比如我们开发一个模块给别人用,但是有一些函数只允许在模块的内部进行调用,不想暴露给外部,那么就可以将这些函数用internal关键字进行修饰
数据类和单例
数据类通常需要重写equals,hashCode,toString方法,其中equals方法用于判断两个数据是否相等,hashCode方法是equals方法的配套方法,toString方法用来打印更为清晰的日志,否则数据打印出来就是一串地址
在java当中就要一一的实现这些方法
但是在Kotlin当中,只需要使用date关键字就可以解决
data class Cellphone(val brand: String, val price: Int)
在上面这行代码中,我就定义了一个数据类,当一个date关键字放在class前面的时候,就表明自己希望这个类是一个数据类,Kotlin会根据主构造函数中的参数帮这个类将equals,hashCode,toString方法进行了重写,另外当一个类中没有任何代码时候,类的{}可以进行省略
接下来就是单例类,单例模式是一种基础的设计模式,当我们在开发的过程中,希望某个类在全局最多只能有一个实例,这样就可以使用单例模式,单例模式使用java语言的编写方式有很多种,虽然简单,但是在Kotlin中还有更加简单的方法
在Kotlin当中创建一个单例类十分简单,只需要将class关键字改成object关键字即可,在创建类的时候直接选择object不要选择class即可
object Singleton { }
现在Singleton就已经是一个单例类,我们可以直接在这个类当中编写需要的函数,比如加上一个singletonTest方法
object Singleton { fun singletonTest() { println("this is a singleTon.") } }
可以看到在Kotlin当中我们不需要私有化构造函数,也不需要提供getInstance()这样的静态方法,只需要将class关键字修改该成为object关键字即可
上述代码在调用的时候直接使用Singleton.singletonTest()即可,这种写法看上去像是静态方法调用,但是实际上Kotlin在背后自动帮我们创建了一个Singleton类的实例
加载全部内容