Kotlin 类与面向对象编程(读书笔记)

第4章 面向对象编程简史

Java 是一种面向对象编程语言,它基于 Smalltalk 语言,作为 OOP 语言,它具有以下5个基本特性:

  • 万物皆对象,每一个对象都会存储数据,并且可以对自身执行操作。因此,每一个对象包含两部分:成员变量和成员方法。在成员方法中可以改变成员变量的值。
  • 程序是对象的集合,他们通过发送消息来告知彼此所要做的事情,也就是调用相应的成员函数。
  • 每一个对象都有自己的由其他对象所构成的存储,也就是说在创建新对象的时候可以在成员变量中使用己存在的对象。
  • 每个对象都有其类型,每个对象都是某个类的一个实例,每一个类区别于其他类的特性就是可以向它发送什么类型的消息,也就是它定义了哪些成员函数。
  • 某一个特定类型的所有对象都可以接受同样的消息。另一种对对象的描述为:对象具有状态(数据,成员变量)、行为(操作,成员方法)和标识(成员名,内存地址)。

关于面向对象编程的基本概念如图所示
Kotlin 类与面向对象编程(读书笔记)_第1张图片

4.2 声明类

4.2.1 空类

class AnEmptyClass
fun main(args : Array<String>} {
     
  val anEmptyClass = AnEmptyClass (){
     
  println(anEmptyClass) 
  println(anEmptyClass is AnEmptyClass) 
  println(anEmptyClass : :class)

//输出如下 :
com.easy.kotlin.AnEmptyClass@2626b418
true
class com.easy.kotlin.AnEmptyClass (Kotlin reflection is not available}

4.2.2 声明类和构造函数

在 Kotlin 中,我们可以在声明类的时候同时声明构造函数,语法格式是在类的后面使用括号包含构造函数的参数列表

//声明类和构造函数
class Person (var name: String, var age: Int, var sex: String){
     

    //override 关键字,重写 toString()
    override fun toString(): String {
     

        return "Person(name=’$name’, age=$age, sex=’$sex’)"
    }
}

//测试
val person = Person(”Jack", 29,”M”) 
println(”person =${
     person))

//输出
person= Person(name=’ Jack ’, age=29 , sex=’M’)

另外,也可以先声明属性,等构造实例对象的时候再去初始化属性值,那么 Person 类可以进行如下声明 :

	
	class Person1 {
     

    	lateinit var name: String //lateinit 关键字表示该属性延迟初始化
    	var age: Int = 0		  //lateinit 关键字不能修饰 primitive 类型
    	lateinit var sex: String

    	override fun toString(): String {
     

        return "Personl(name= '$name', age=$age , sex='$sex' )"
    	}
	}	
 	//测试
    val person1 = Person1()
    person1.name = "Jack"
    person1.age = 26
    person1.sex = "M"
    println("person1= $person1")

    //输出
    person1 = Personl(name = 'Jack', age =26, sex = 'M')

如果我们想声明一个具有多种构造方式的类,可以使用 constructor关键字声明构造函数

class Person2() {
        //无参的主构造函数

    lateinit var name: String
    var age: Int = 0
    lateinit var sex: String

	//次级构造函数,this 关键字指向当前类对象实例
    constructor(name: String) : this() {
         

        this.name = name
    }
    
    //次级构造函数
    constructor(name: String, age: Int) : this(name) {
        

        this.name = name
        this.age = age
    }

	//次级构造函数
    constructor(name: String, age: Int, sex: String) : this(name, age) {
        

        this.name = name
        this.age = age
        this.sex = sex
    }

    override fun toString(): String {
     

        return "Personl(name= '$name', age=$age , sex='$sex' )"
    }

}

实际上, 我们在 编程实践中用到最多的构造函数还是这个 :

class Person (var name: String , var age : Int , var sex : String)

当需要通过比较复杂的逻辑来构建一个对象的时候,可采用构建者( Builder )模式来实现。

4.3 抽象类与接口

抽象类表示“ is-a”的关系,而接口所代表的是“ has-a”的关系。例如,设计一个图形编辑软件,问题领域中存在着长方形 (Rectangle)、圆形( Circle)、 三角形( Triangle)等一些具体概念,它们是具象。但是它们又都属于形状(Shape)这个抽象的概念。
Kotlin 类与面向对象编程(读书笔记)_第2张图片

4.3.1 抽象类与抽象成员

抽象是相对于具象而言的。
因为抽象的概念在问题领域中没有对应的具体概念,所以抽象类是不能够实例化的。

abstract class Shape        //声明抽象父类 Shape
class Rectangle : Shape()   //继承类的语法是使用冒号“:” ,父类需要在这里使用构造函数进行初始化
class Circle : Shape()      //Circle 继承Shape类
class Triangle : Shape()    //Triangle 继承Shape类

当子类继承了某个类之后,便可以使用父类中的成员变量,但并不是完全继承父类的所有成员变量。具体的原则如下 :

  • 能够继承父类的 public 和 protected 成员变量,不能继承父类的 private成员变量
  • 对于父类的包访问权限成员变量,如果子类和父类在同一个包下,则子类能够继承,否则,子类不能继承
  • 对于子类可以继承的父类成员变量,如果在子类中出现了同名称的成员变量,则会发生隐藏现象,即子类的成员变量会屏蔽掉父类的同名成员变量。如果要在子类中访问父类中的同名成员变量,需要使用 super 关键字进行引用。

4.3.2 接口

接口是一种比抽象类更加抽象的“类“。接口本身代表的是一种”类型“的概念。但在语法层面,接口本身不是类,不能实例化接口,只能实例化它的实现类 。
Kotlin与 Java一样, 不支持同时继承多个父类,也就是说继承 只能存在一个父类(单继承)。
和 Java类似, Kotlin使用 interface作为接口的关键词:

interface A {
     

    val name: String
    val owner: String
    fun save(project: A)
    fun print() {
     

        println("I am project")
    }
}

interface B {
     

    val name: String
    val owner: String
    fun save(project: B)
    fun print() {
     

        println("I am Milestone")
    }
}

class ProjectMilestoneServiceImpl(override val name: String, override val owner: String) :
    A, B {
     

    override fun print() {
     
        //super.print()
        super<B>.print()
    }

    override fun save(a: A) {
     

        TODO("Not yet implemented")
    }

    override fun save(b: B) {
     
        TODO("Not yet implemented")
    }
}

在重写 print()函数时,因为我们实现的 ProjectService、MilestoneService都有一个 print() 函数,当直接使用 super.print() 函数时,编译器无法知道我们想要调用 的是哪个 print 函数,这种现象叫做覆盖冲突。这个时候 ,我们可以 使用下面的语法来调用 :

super<A>.print()
super<B>.print()

4.4 object 对象

Kotlin 中没有静态属性和方法,但是可以使用关键宇 object 声明一个 object单例对象


object User {
     				//声明对象类型User
	val username: String = "admin"
	val password: String = "admin"
	fun hello() {
     
		println(” Hello, object !)
	}
}
fun main(args : Array<String>) {
     

	println(User .username)
	println(" Hello, object !")
	User.hello() //与Java静态类的调用形式一样
}

Kotlin 中还提供了伴生对象, 用 companion object 关键字声明:

class DataProcessor {
     

    companion object A {
     

        fun process() {
     

            println("I am processing data....")
        }
    }
}
fun main (args : Array<String>) {
     

    DataProcessor.process()
}

一个类只能有 一个伴生对象 。

4.5 数据类

数据类就是只存储数据,不包含操作行为的类。 Kotlin 中的数据类可以为我们节省大量的样板代码

4.5.1 创建数据类

使用关键字为 data class 创建一个只包含数据的类 :

data class LoginUser(val username : String, val password : String)

4.5.2 数据类自动创建的函数

自动创建以下 3 个函数

  • equals()、hashCode()、toString() 格式为 ”LoginUser(username=”+this.username+”,password=”+this.password+”)“
  • component1()和 component2()函数返回对应下标的属性值,按声明顺序排列
  • copy()函数:根据旧对象属性重新 newLoginUser(username,password)一个对象出来。 如果这些函数在类中已经被明确定义了,或者从超类中继承而来,编译器就不再生成。

4.5.3 数据类的语法限制

数据类有如下限制 :

  • 主构造函数至少包含一个参数
  • 参数必须标识为val或者var
  • 不能为 abstract、 open、 sealed 或者 inner
  • 不能继承其他类(但可以实现接口)
  • 数据类可以在解构声明中使用
data class LoginUser(val username: String, val password: String)

fun main(args: Array<String>) {
     

    val loginUser = LoginUser("admin", "admin")
    val (username, password) = loginUser
    println("username=$username,    password=$password")
}

4.5.4 Pair 和 Triple

Kotiin 标准库提供了 Pair和 Triple数据类, 分别表示二元组和三元组对象。

data class Pair<out A, out B>(val first: A, val second: B) : Serializable {
     

    override fun toString(): String = "($first,$second)"
}

使用 Pair 对象来初始化一个 Map

4.6 注释

4.7 枚举

Katlin中使用 enumclass关键字来声明一个枚举类, 枚举类有两个内置的属性 ,分别表示的是枚举对象的值与下标位置

enum class Direction {
     
	NORTH,SOUTH,WEST,EAST
}

枚举对象的信息如下 :
Kotlin 类与面向对象编程(读书笔记)_第3张图片
每一个枚举都是枚举类的实例,它们可以被初始化
Kotlin 类与面向对象编程(读书笔记)_第4张图片
枚举对象的信息如下 :
Kotlin 类与面向对象编程(读书笔记)_第5张图片

你可能感兴趣的:(Kotlin,kotlin)