Kotlin—面向对象(一)

在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才初始化
    }
}

注意点

  1. 不能使用val来声明
  2. 不能为空
  3. 不能初始化

错误示范

    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([email protected])   //访问外部类属性
            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")
    }

}

猜你喜欢

转载自blog.csdn.net/qq_41346910/article/details/88413974
今日推荐