其他分享
首页 > 其他分享> > 跟郭神学Kotlin(第三行学习笔记02)

跟郭神学Kotlin(第三行学习笔记02)

作者:互联网

郭神在开头解释了面向对象的含义,我觉得最经典的一句话就够了。

万物皆对象

类与对象

Kotlin 中 定义一个类也是用 Class 关键字

//一个类的空实现
class Person {

}

再申明一些 变量 和 函数

class Person {

    var name = ""//注意这里定义是var 否则后边就无法赋值了
    var age = 0//Kotlin变量必须初始化赋值 否则无法通过编译

    fun eat() {
        println(name + "正在吃茄子。他今年" + age + "岁了!")
        println("${name}正在吃茄子。他今年${age}岁了!")//也可以用这种写法
    }

}

然后我们来实例化 一个类

fun testClass() {
    val person = Person()
    
    person.age = 6
    person.name = "臭弟弟"
    person.eat()
}

可以看到 和Java 类似 只是 没有了 new,因为Kotlin本着最简化的设计原则 即使没有 new 也能表达 我要new 一个对象的意图。

继承与构造函数

申明一个 Student 类 继承上面的 Person

不过 首先需要将 Person 变得可继承 这一点和Java中有点不一样(其实是我们用法习惯不规范——如果一个类不是专门为继承而设计的,那么它应该加上final禁止它可以被继承)

open 关键字

open class Person {

    var name = ""
    var age = 0

    fun eat() {
        println(name + "正在吃奥利给。他今年" + age + "岁了!")
        println("${name}正在吃奥利给。他今年${age}岁了!")
    }

}

加 open 的作用 就是告诉编译器,我这个类就是专门为了继承而申明的。

然后 在 Student中 使用 : Person() 即可 这里的 :就等于 Java 中的 extends 关键字。

class Student : Person() {
    var sno = ""
    var grade = 0
}

主构造函数

每个类默认都会有一个不带参数的主构造函数,也可以显示指定参数。

class Student : Person() {

}

主构造函数的特点就是没有函数体,直接定义在类名后即可。如下:

class Student(val sno:String,val grade:Int) : Person() {
    var sno = ""
    var grade = 0
}

//指定一个Student
val student = Student("2008AD36", 8)

init 结构体

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

    init {
     println("sno is $sno")
     println("grade is $grade")
    }

}

如果想在主构造函数里写逻辑 可以用使用 init 结构体
Java继承特性的一个规定:子类中的构造函数必须调用父类中的构造函数,Kotlin也一样
所以说

Student : Person() 的 这个括号() 其实就是Person这个父类的构造函数

如果将父类申明主构造函数

open class Person(val name:String,val age:Int) {

}

那么子类就会报错,此时子类应该这样写

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

}
//其中 name: String,age:Int 就是父类主构造函数中的参数

这里 需要值得注意的是:Student子类主构造函数中增加的name和age不能再将它们申明成 val 。因为在主构造函数中申明为 val/var 的参数将自动转化为该类的字段,这会导致和Person父类中的 name和age冲突。因此 这里 不需要加任何关键字 让它的作用域仅限主构造函数即可。(虽然很长 但是感觉很重要 还是要说一下)

val student = Student("2021", 8,"臭弟弟",6)

任何一个类只能有一个主构造函数和多个次构造函数。

次构造函数

Kotlin规定,当一个类既有主构造又有次构造时,所有次构造函数都必须调用主构造函数(包括间接调用)。

constructor关键字

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

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

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

}

可以看到,最前边是 constructor关键字 来定义,最后跟了个 this关键字 来调用主构造函数。这时,我们就可以通过次构造函数来实例化 Student类

val student0 = Student("2021", 8, "臭弟弟", 6)

val student1 = Student("2019", 24)

val student2 = Student()

特殊情况:类中只有次构造,没有主要构造

当一个类没有显式地定义构造函数且定义了次构造函数时,它就没有主构造函数。

class Student : Person {

    constructor(name: String, age: Int) : super(name, age) {
    }

}

这里,Student类后边没有显式地定义主构造函数,同时又定义了次构造函数,所以这里Student类没有主构造函数。所以Person类后边就无需加括号了。再由于没有主构造函数,所以次构造函数可以直接调用父类的构造函数,所以这里 this 变为了 super

接口

Kotlin中的接口几乎和Java一致。Kotlin也是单继承,多接口。我们可以在接口中定义一系列抽象行为,然后由具体的类去实现。

interface Study {

    fun readBook()
    fun doHomework()

}

在上面的 Student类 中实现我们的 Study接口

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

    override fun readBook() {
        println(name + "在读书")
    }

    override fun doHomework() {
        println(name + "在做作业")
    }

}

对比Java的继承(extends)和接口实现(implements)来看,kotlin的( : )和( , )更加简化。

面向接口编程/多态

fun main(){
    val student = Student("茄子", 99)
    doStudy(student)
}

fun doStudy(study: Study){
    study.doHomework()
    study.readBook()
}

可以看到,doStudy()接收一个Study类型的参数,由于Student类实现了Study接口,因此Student类的实例是可以传递给doStudy()函数的。接下来调用Study接口里的函数,这种就叫作 面向接口编程 ,也可以成为 多态

接口函数的默认实现

Kotlin和JDK1.8都支持 对接口中定义的函数进行默认实现。

interface Study {

    fun readBook()
    fun doHomework(){
        println("我TM在写作业")
    }

}

同样是Study接口,我们给doHomework函数加上了函数体。

如果接口中的一个函数拥有函数体,这个函数体中的内容就是它的默认实现。现在当一个类去实现Study接口时,只会强制要求实现readBook()函数,而doHomework()函数则可以自由选择实现或者不实现,不实现时就会自动使用默认的实现逻辑。

可见性修饰符

Java有

public,private, protected, default(默认)

而kotlin有

public(默认),private, protected, internal

Java和Kotlin修饰符的异同

对照表

修饰符Javakotlin
public所有类可见所有类可见(默认)
private当前类可见当前类可见
protected当前类,子类,同一包路径下的类可见当前类,子类可见
default同一包路径下的类可见(默认)
internal同一模块中的类可见

数据类和单例类

数据类

data 关键字

/**
 * 数据类 演示
 */
data class Cellphone(val brand: String, val price: Double) {

}

当一个类在前面申明了 data 关键字时,就表示这个类是一个数据类,Kotlin会根据主构造函数中的参数自动帮你将equals()hashCode()、**toString()**等方法自动生成。
验证一下打印

fun testCellphone(){
    val cellphone1 = Cellphone("Realme",2999.99)
    val cellphone2 = Cellphone("Realme",2999.99)

    println(cellphone1)
    println("1 equals 2 is : "+(cellphone1==cellphone2))

}

//输出了
Cellphone(brand=HuaWei, price=2999.99)
1 equals 2 is : true

//然后去掉Cellphone前面的data关键字再次输出
info.itloser.line3code.Cellphone@27c170f0
1 equals 2 is : false

可以看到 有data时 输出的是我们想要的值,去掉data时 输出的是整个对象。

单例类

Kotlin中特有的功能 单例类
在Java中我们一般都称为单例模式

/**
 * Java中的的单例模式
 */
public class Singleton {

    private static Singleton instance;

    private Singleton(){}

    public synchronized static Singleton getInstance(){

        if (instance==null){
            instance = new Singleton();
        }

        return instance;

    }

    public void singletonTest(){
        System.out.println("This is Java singleton test");
    }
    
}

调用其中的方法

Singleton singleton = Singleton.getInstance();
singleton.singletonTest();

Kotlin的单例类 更简单 只需要
在创建Kotlin类时 选择 类型为Object 即可

/**
 * 一个Kotlin的单例类
 */
object Singleton {

    fun singletonTest(){
       println("This is Kotlin singleton test");
    }

}

可以看到,Kotlin的单例类是简单了很多,无需什么getInstance等方法
当然调用也很简单

Singleton.singletonTest()

标签:02,name,val,第三行,Kotlin,age,Person,Student,构造函数
来源: https://blog.csdn.net/qq_38376757/article/details/114004390