美文网首页
Kotlin面向对象编程

Kotlin面向对象编程

作者: code希必地 | 来源:发表于2020-09-19 13:29 被阅读0次

1、类与对象

Kotlin中类的声明和Java类一样,都是用关键字class来声明类

class Person {
    var name = ""
    var age = 0

    fun introduce() {
        Log.e("TAG", "我的名字叫" + name + " 我已经" + age + "岁了")
    }
}

Person类已经定义完成,那如何创建Person类的对象呢?

 val p = Person()

和Java类似,只是剩去了new,这样也很好理解:Person()代表的是构造函数,而只有创建对象时才会调用构造函数,这样编码的意图也很明显就是创建对象。
接下来我们就能使用对象进行一些操作:

fun createPerson() {
        val p = Person()
        p.age=100
        p.name="张丹"
        p.introduce()
    }

2、继承与构造函数

  • 1、在Kotlin中非抽象类、非接口默认是不能被继承的,要想某个类能被继承,就需要使用关键字open
open class Person{
}
  • 2、使用:来表示继承关系
class Student :Person() {
}

细心的你肯定也发现了Person后加了一对小括号,这又是为什么呢?这就和Kotlin中的主构造函数和次构造函数有关系了,

2.1、主构造函数

  • 1、Kotlin中每个类都默认有一个无参的构造函数来作为主构造函数,而且主构造函数有且仅有一个,次构造函数的个数不限。
  • 2、我们也可以给主构造函数显示的指定参数
class Student(val sno: String, val grade: Int) : Person() {
}

我们将学号和年级在主构造函数中声明了,所以在创建Student对象的时候就必须传入主构造函数中要求的所有参数。

  • 3、主构造函数没有方法体,直接在类名后定义即可。
    如果我想在主构造函数中写一些逻辑该怎么办呢?Kotlin给我们提供了init结构体,所有主构造函数中逻辑可以写在结构体中。
class Student(val sno: String, val grade: Int) : Person() {
    init {
        //在创建Student对象时就会执行这个结构体
        Log.e("TAG","我是主构造函数,学号sno:"+sno+" 年级grade:"+grade)
    }
}
  • 4、在java中子类的构造函数必须要调用父类的构造函数,在Kotlin中也是如此。上面在继承Person时Person后面加了一对括号的用处就是在创建Student对象时指定在Student的构造函数中调用父类的那个构造函数。
    下面我们对Person修改一下,将name和age放在主构造函数中
open class Person(val name: String, val age: Int) {
}

此时Student类肯定会报错,因为在Student类中我们指定调用父类的无参构造,而无参构造已经不存在了,必须给Person类传入name和age。可是在Student中并没有name和age,我们可以在Student中加入name和age

class Student(val sno: String, val grade: Int, name: String, age: Int) : Person(name, age) {
}
  • 5、注意:在Student类的主构造函数中加入的name和age不能使用val或var修饰,因为在主构造函数中使用val或var修饰的参数将自动变成该类的字段,这就导致和父类中的name、age同名导致的冲突。

2.2、次构造函数

  • 1、其实在Kotlin中我们一般用不到次构造函数,因为Kotlin中提供了给函数设定参数默认值的功能,基本可以替代次构造函数。
  • 2、一个类只有一个主构造函数,但是可以有多个次构造函数。和主构造函数不同的是,次构造函数是有方法体的。
  • 3、Kotlin规定:当一个类中既有主构造函数又有次构造函数时,所有的次构造函数必须调用主构造函数(包含间接调用)
class Student(val sno: String, val grade: Int, name: String, age: Int) : Person(name, age) {

    init {
        Log.e("TAG", "我是主构造函数,学号sno:" + sno + " 年级grade:" + grade)
    }

    constructor(name:String,age:Int) : this("",0,name,age) {

    }

    constructor():this("",0){

    }

}
  • 4、次构造函数是通过关键字constructor定义的,这里我们定义了两个次构造函数:第一个次构造函数传入name和age作为参数,然后通过this关键字调用了主构造函数;第二个次构造函数没有参数,它通过this关键字调用了第一个次构造函数间接的调用了柱构造函数,这也是合法的。现在我们就有3种方式创建Student的实例了
val stu1=Student("张无忌",50)
stu1.introduce()

val stu2=Student()
stu2.introduce()
        
val stu3=Student("10010",5,"尹力",130)
stu3.introduce()
  • 5、如果一个类中没有显式的定义主构造函数,而使用关键字constructor定义了次构造函数,那么类中是没有主构造函数的
class Teacher : Person {
    constructor(name: String, age: Int) : super(name, age) {
    }
}

注意这里代码的变化,Teacher类中没有显式的定义主构造函数并且定义了次构造函数,所以Teacher类是没有主构造函数,由于没有主构造函数,所以在继承Person类时也就不需要加扩号,原因很简单:由于Teacher类没有主构造函数,所以我们不能通过主构造函数来创建Teacher的实例,即使Kotlin允许此时添加括号,也是无法达到调用父类构造的目的。我们只能通过次构造函数创建实例,我们只能通过super来调用父类的构造函数。

3、接口

Kotlin中和Java一样都是单继承的,一个类只能继承一个父类,但是可以实现多个接口。和Java一样也是通过interface声明接口

interface Study {
    fun readBook()
    fun doHomeWork()
}

Student类实现Study的接口,并实现其中的方法

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

    init {
        Log.e("TAG", "我是主构造函数,学号sno:" + sno + " 年级grade:" + grade)
    }

    constructor(name: String, age: Int) : this("", 0, name, age) {

    }

    constructor() : this("", 0) {

    }

    override fun readBook() {
    }

    override fun doHomeWork() {
    }
}
  • 1、Kotlin中实现接口和集成一样都是使用:,类和接口间使用,隔开,另外接口的后面不需要加括号,因为接口根本就没有构造可以被调用
  • 2、Kotlin中使用关键字override来重写父类的方法或实现接口中的方法,另外如果父类中的方法需要被重新的话,需要在方法前增加关键字open,否则无法重写。
  • 3、Kotlin中的接口可以有默认的实现,接口中有默认实现的方法子类可以不实现。
interface Study {
    fun readBook(){
        Log.e("TAG","接口中的方法可以默认实现")
    }
    fun doHomeWork()
}

4、修饰符

在Kotlin中函数的可见性修饰符相比于Java变动还是很大的。直接上表

修饰符 Java Kotlin
public 所有类可见 所有类可见(默认修饰符)
private 当前类可见 当前类可见
protected 当前类、子类、同一包下的类可见 当前类、子类可见
default 当前类、统一包下类可见
internal 同一模块下可见

5、单例和数据类

5.1、数据类

数据类通常要重写equals()、hashCode()、toString()几个方法,其中eaquals()判断两个数据类是否相等,hashCode()作为eqauls()的配套方法,也需要重写否则会导致HashMap、HashSet中相关hash的操作不能正常工作,toString()是为了提供了一个清晰的日志输出,否则打印出来就是内存地址。下面举个简单的例子:

public class CellPhone {
    String brand;
    double price;

    public CellPhone(String brand, double price) {
        this.brand = brand;
        this.price = price;
    }

    @Override
    public boolean equals(Object o) {
        if (o instanceof CellPhone) {
            CellPhone cellPhone = (CellPhone) o;
            return cellPhone.price == price && cellPhone.brand.equals(brand);
        }
        return false;
    }

    @Override
    public int hashCode() {
        return brand.hashCode() + (int) price;
    }

    @Override
    public String toString() {
        return "CellPhone:brand:" + brand + " price:" + price;
    }
}

在Kotlin的实现上述功能就只需一句代码即可。

data class CellPhone(val brand: String, val price: Double) 

神奇的地方就在于data关键字,在Kotlin中的类声明了data关键字,那么这个类就是一个数据类,Kotlin中会根据主构造函数中的参数自动生成eqauls()、hashCode()、toString()等方法并实现相应的逻辑。另外在一个类中没有任何代码时,可以省了大括号
下面我们测试下该类

fun testDataClass() {
        val cellPhone1 = CellPhone("xiaomi", 2000.0)
        val cellPhone2 = CellPhone("xiaomi", 2000.0)
        Log.e("TAG", "cellPhone1:" + cellPhone1.toString()+"  cellPhone2:"+cellPhone2.toString()+"  cellPhone1.equals(cellPhone2):"+(cellPhone1==cellPhone2))
    }

输出:
cellPhone1:CellPhone(brand=xiaomi, price=2000.0)  cellPhone2:CellPhone(brand=xiaomi, price=2000.0)  cellPhone1.equals(cellPhone2):true

很明显CellPhone已经正常工作了。

5.2、单例类

在Java中的实现

public class SingleInstance {
    private static SingleInstance instance;

    private SingleInstance() {
    }


    public static synchronized SingleInstance getInstance() {
        if (instance == null) {
            instance = new SingleInstance();
        }
        return instance;
    }

}

在Kotlin中创建一个单例类很简单,只需要将class关键字改成object关键字即可。

object SingleInstance {
}

现在SingleInstance就是一个单例类了,我们可以直接在这个类中编写需要的函数,比如加入一个singleInstanceTest()

object SingleInstance {

    fun singleInstanceTest() {
        Log.e("TAG","singleInstanceTest is called")
    }
}

可以看到,Kotlin不需要私有化构造函数,也不需要提供getInstance()这样的静态函数,只需要将class修改为object,Kotlin就帮我们生成了单例类相关的逻辑,它的调用也很简单

SingleInstance.singleInstanceTest()

这种写法看上去像是静态方法的调用,其实Kotlin内部已经帮我们生成了SingleInstance实例,并且该实例有且仅有一个。

相关文章

  • Kotlin面向对象 (1)✔️类、及属性

    Kotlin语言目前还是以面向对象编程为主,函数式编程为辅。什么是面向对象?面向对象的三大基本特征,封装性、继承性...

  • Kotlin 初识

    一 :什么是Kotlin Kotlin是一种开源的静态类型编程语言,支持面向对象和函数式编程。Kotlin提供了与...

  • 《Kotlin 程序设计》第五章 Kotlin 面向对象编程(O

    第五章 Kotlin 面向对象编程(OOP) 正式上架:《Kotlin极简教程》Official on shelv...

  • Kotlin面向对象编程

    1、类与对象 Kotlin中类的声明和Java类一样,都是用关键字class来声明类 Person类已经定义完成,...

  • Kotlin——面向对象编程

    一、作用 二、概念 1. 类与对象 类是对事物的一种封装,可以拥有属性和行为。(1)定义类class关键字 (2)...

  • Kotlin面向对象编程笔记

    Kotlin语言基础笔记 Kotlin流程控制语句笔记 Kotlin操作符重载与中缀表示法笔记 Kotlin扩展函...

  • kotlin-面向对象编程

    1.类和对象[https://www.jianshu.com/p/b0bfd7cea12e]2.接口[https:...

  • 第六篇:Kotlin之面向对象简单

    上篇:Kotlin之函数Lambda表达式 下篇:Kotlin之面向对象升级(一) Kotlin也支持面向对象的三...

  • 面向对象_初识

    目录 面向对象编程介绍 类与对象介绍 私有属性与私有方法 面向对象编程 1. 面向对象编程介绍 面向对象编程:Ob...

  • kot

    #Kotlin之班门弄斧 ##面向对象 ##java和kotlin的交互 ##协程及协程框架 ## 面向对象 ...

网友评论

      本文标题:Kotlin面向对象编程

      本文链接:https://www.haomeiwen.com/subject/pjgdyktx.html