在Kotlin中有两大思想,分别是面相对象编程和函数式编程,从今起进入我们就要攻克这两大核心思想,先是面相对象的学习和使用。
一、面相对象三大特征
先简单介绍面相对象的知识,你现在只需要有一个抽象的认识。
说起面相对象就要说一下面向过程
面向过程:分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。
面向对象:把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。
直观点解释比如:一个围棋游戏,面相过程就是设计开始游戏画面,然后初始化棋盘,判断需要时间,然记录等。
而面相对象,则是创建开始游戏和棋盘、棋子、记录等。
封装
将某些信息隐藏在内部,不允许外部程序直接访问,而是通过提供的函数来实现对隐藏信息的操作和访问。
继承
继承就是获取到父亲的属性和函数,可以在自己使用也可以更改或者重写
多态
通常在搭建框架中使用。
二、面相对象基础
1 类
从创建一个类开始,在一个类中可以有很多属性和函数。Kotlin中的类Java的类比较类似。
new 一个Kotlin Class,取个名字就行。
class Demo {
}
这就是一个简单的Class,是面对象中经常使用的基础单位。
2 属性
在Kotlin中声明一个属性很简单,只需要 var或者val+属性名称+=值
val name="王"
当然你可以加上属性类型,然后告诉可空类型,然后不给值
var name:String? = null
2.1.延迟属性
延迟属性在Java没有的,一般我们都是先赋值null,再在需要的时候赋值。在Kotlin中就是使用关键字
lateinit var student: Student //引用数据类型
lateinit var s: String //基本数据类型
这样的好处是在使用的时候才开辟内存,进行初始化,节约内存。
下面的Demo类中声明延迟属性是并没有初始化,二十在调用是才初始化再调用
class Demo {
lateinit var p: Person //声明延迟属性
fun test() {
println(p.name) //在这Person才初始化
}
}
注意点
- 不能使用val来声明
- 不能为空
- 不能初始化
错误示范
lateinit var student: Student = null //不能为空
lateinit val s: String //不能为val
lateinit var student2: Student = Student() //不能初始化
3扩展
在Kotlin中拥有一种机制叫扩展,它在类的外面直接扩展属性和函数。
3.1扩展属性
class Person() {
val name: String = "王"
}
var Person.id: String
get() = "Person的id为1"
set(value) = println(value)
fun main(args: Array<String>) {
var person=Person()
println(person.id)
}
结果
3.2.扩展函数
class Person() {
val name: String="王"
}
fun Person.person(){
println("Person的扩展函数person")
}
fun main(args: Array<String>) {
var person=Person()
person.person()
}
2.3.成员属性和扩展属性优先级
成名属性优先级比扩展属性高,
class Person() {
val name: String = "王"
}
var Person.name: String
get() = "控制name"
set(value) {
println(value)
}
fun main(args: Array<String>) {
var person=Person()
println(person.name)
}
结果
3.缀运算符
什么缀运算符,就是经常使用的+,-啊,都是。
infix fun Int.add(int: Int): Int {
return this + int
}
fun main(args: Array<String>) {
var a=1
println(a add 1)
}
结果:
4.构造函数
构造函数,分为两种,主构造函数,和次构造函数。主构造函数在类的名称后面,次构造函数则在类里。
4.1主构造函数
和Java相同每一个类都有默认的构造函数,既无参构造函数。
class Person() {
fun p() {
println("使用无参构造函数,创建对象")
}
}
fun main(args: Array<String>) {
var person = Person(); //这里就是使用无惨构造函数创建对象
person.p()
}
结果:
有参构造函数
class Person(name: String) {
var name = name
}
fun main(args: Array<String>) {
var person = Person("王"); //使用有参构造函数
println(person.name)
}
结果:
完整写法
class Person constructor(name: String) {
var name: String
init {
this.name = name
}
}
fun main(args: Array<String>) {
var person = Person("王");
println(person.name)
}
当然constructor可以省略掉,也要注意不能省略的情况。
灵活使用
public class Person(var name: String, var sex: Boolean = true) {
}
4.2次构造函数
当主构造函数,不够灵活时,可以使用次构造函数,来方便使用。
fun main(args: Array<String>) {
var person = Person("wang"); //使用主构造函数
var person2 = Person("wang", false) //使用次构造函数
var person3 = Person("wang", false,1) //使用次构造函数
}
public class Person(name: String) {
var name: String
var sex = true
var age: Int = 0
init {
this.name = name
}
constructor(name: String, sex: Boolean) : this(name) {
this.sex = sex
}
constructor(name: String, sex: Boolean, age: Int) : this(name) {
this.sex = sex
this.age = age
}
}
5.可见性修饰符
1.共有的修饰符
public 是kotlion默认修饰符,它可以申明类、函数、属性,也可以声明顶层的函数和属性,它属于公共的。
2.保护修饰符
protected和Java的一样,只有子类继承后才可以使用。
3.内部可见性修饰符
internal 是模块可见,在同一个模块和public,在不同的模块和private相似。注意,模块不是包和Java不同
4.私有修饰符
private 就是只有自己才可以访问到。
6.Any类
Any类和java的Object类。所有Kotlin中的类都继承了Any类。这个类里有三个函数
equals:比较其它对象是否和这个对象相等
hashCode:返回改对象的哈希码
toSting:返回该对象的字符串表示
7.数据类
使用data声明的类叫数据类,它自动重写Any中的三个函数和一个copy函数。
声明一个data类
data class Person(var name: String,var sex:String,var age:Int) {
}
注意data类不能省略var或者val
copy函数使用
fun main(args: Array<String>) {
var p = Person("wang", "nan", 20)
var a = p.copy()
println(p)
println(a)
println(p==a)
}
此时a就和p一样了
解构data类
解构和创建都是对对象操作的。创建一个对象使用构造函数,解构一个对象,就是被一个对象中属性拿出来。
fun main(args: Array<String>) {
var p = Person("wang", "nan", 20)
val (name, sex) = p
println(name)
println(sex)
}
这里的括号对应这构造函数的属性的顺序。
结果:
一般,你不会全部使用,对象里的值,你可以这样
fun main(args: Array<String>) {
var p = Person("wang", "nan", 20)
var (name) = p
var (name2, _) = p
println(name)
println(name2)
}
8.枚举类
枚举类是用来管理一堆常量的。
9.嵌套类
class Person() {
var name: String? = null
class Hand() {
fun hand() {
println("手")
println(name) //报错
}
}
}
fun main(args: Array<String>) {
var person = Person()
val hand = Person.Hand()
}
嵌套类不能访问外部类
10.内部类
内部类可以访问外部类属性和函数。
class Person() {
var name: String? = "人"
var age = 20
inner class Hand() {
var name: String = "手"
fun hand() {
println(this@Person.name) //访问外部类属性
println(this.name) //访问内部类属性
println(name) //访问内部类属性
println(age) //访问外部类属性
}
}
}
内部类创建是和嵌套类使用不同,它需要先创建外部类对象,再创建内部类对象。
fun main(args: Array<String>) {
var person = Person()
val hand = person.Hand()
hand.hand()
}
结果:
二、object关键字
声明并且创建一个类,可以用于对象表达式、对象声明和伴生对象
声明匿名内部类
fun main(args: Array<String>) {
object : InterfaceDemo {
override fun demo() {
}
}
}
object代表一个类,然后实现了一个接口,重写它抽象方法
也可以继承一个类和实现接口
var person = object : Person(), InterfaceDemo {
override fun demo() {
}
}
也可以直接声明一个类使用
var person = object {
var name: String = "wang"
}
声明一个单例模式
object Person {
var name: String? = "人"
var age = 20
fun hand() {
println("hand")
}
}