Kotlin——面向对象(下)

2023-09-27  本文已影响0人  So_ProbuING

扩展

Kotlin支持扩展方法和扩展属性

扩展方法

Kotlin的扩展其实就是定义一个函数,只是函数名不要写成简单的普通函数,而是在函数名前增加被扩展的类(接口)名和点号“.”

fun main(args: Array<String>) {
    //row
    var r = Row()
    r.test()
    //调用扩展方法
    r.extendsFun("hello")
    //子类调用父类的方法
    var sr = SubRow()
    sr.test()
    //子类调用自己的方法
    sr.sub()
    //子类调用父类的扩展方法
    sr.extendsFun("sub")
}

open class Row{
    fun test(){
        println("Row的test方法")
    }
}

class SubRow: Row() {
    fun sub() {
        println("sub方法")
    }
}

fun Row.extendsFun(name: String) {
    println("扩展的Row方法")
}

扩展属性

Kotlin允许扩展属性,Kotlin扩展属性其实是通过添加getter、setter方法实现的。扩展的属性只能是计算属性

final和open修饰符

可执行“宏替换”的常量

Kotlin提供了const用来修饰可执行“宏替换”的常量,这种常量也被称为"编译时"常量。因为它在编译阶段就会被替换掉

const val MAX_AGE =100
println(MAX_AGE)

上面的代码中,根本就不存在MAX_AGE,当程序执行println时,实际替换为执行println(100),这个替换在编译阶段就完成了

final属性

final属性表明该属性不能被重写。如果程序对属性不使用任何修饰符,Kotlin会自动为该属性添加final修饰

final方法

使用final修饰的方法不可被重写。如果程序不为方法添加任何修饰,Kotlin会自动为该方法添加final修饰

final类

使用final修饰的类不可以有子类,Kotlin也会为没有显式使用open修饰的类添加final修饰

抽象类

抽象成员和抽象类

抽象成员(方法和属性)和抽象类必须使用abstract修饰符来定义,包含抽象成员的类只能被定义成抽象类。抽象类中可以没有抽象成员
规则如下

定义抽象方法,只需在普通方法上增加abstract修饰符,并把普通方法的方法体去掉即可
定义抽象类,只需在普通类上增加abstract修饰符

abstract class Shape{
    init {
        println("shape的初始化块")
    }

    var color = ""

    abstract fun calPerimeter():Double

    //抽象属性不需要初始化
    abstract val type:String
    constructor()
    constructor(color:String){
        println("shape构造器")
        this.color = color
    }

}

创建一个普通类继承抽象类

class Triangle(color:String, private var a:Double):Shape(color){
    override fun calPerimeter(): Double {
        this.a = a
        return a * a * a
    }

    override val type: String = "三角形";

}

fun main(args: Array<String>) {
    var triangle = Triangle("red", 1.0)
    triangle.calPerimeter()
}

密封类

密封类的子类是固定的,密封类的子类必须与密封类本身在同一个文件中,在其他文件中则不能为密封类派生子类

//创建一个密封类
sealed class Appleb{
    abstract fun eat()
}
//创建密封类的子类
open class RedFuJi:Appleb(){
    override fun eat() {
        println("密封类的子类")
    }

}

fun main(args: Array<String>) {
    val a1:Appleb = RedFuJi()
    a1.eat()
}

接口

接口的定义

语法

[修饰符] interface 接口名:父接口1,父接口2...{
//零个到多个属性定义...
//零个到多个方法定义...
//零个到多个嵌套类、嵌套接口、嵌套枚举定义...
}
interface Outputtable{
    //定义属性
    //只读属性 定义get方法
    val name:String
        get() ="只读属性"
    //读写属性 设置get set方法
    var price:Int
        get() {
           return price
        }
        set(value) {
            price = value
        }

    //抽象属性
    var age:Int
    //抽象方法
    fun a1()
    fun a2()
    fun a3()

    //非抽象方法
    fun print(vararg msg: String){
        for (s in msg) {
            println(s)
        }
    }
}

接口的继承

接口完全支持多继承,一个接口可以有多个父接口,一个接口继承多个父接口,多个父接口排在英文冒号:之后,它们之间以英文逗号隔开

使用接口

接口的主要用途就是被实现类实现

class OutputtableImpl:Outputtable{
    override var age: Int
        get() = TODO("Not yet implemented")
        set(value) {}

    override fun a1() {
        TODO("Not yet implemented")
    }

    override fun a2() {
        TODO("Not yet implemented")
    }

    override fun a3() {
        TODO("Not yet implemented")
    }
}

嵌套类和内部类

把一个类放在另一个类的内部定义,这个定义在其他类内部的类就称为嵌套类,包含嵌套类的类就被称为外部类

内部类

内部类相当于外部类的实例成员,因此内部类可以直接访问外部类的所有成员

class Outer(var name:String){
    fun sayName(){
        println("name${name}")
    }
    inner class innerCls(){
        var innerField = ""
        fun sayInnerName(){
            println("sayInner+${innerField}")
            //访问外部类属性
            name
            sayName()
        }
    }
}

fun main() {
    //创建外部类
    var outer = Outer("hh")
    //外部类访问属性
    println(outer.name)
    outer.sayName()
    //创建内部类对象
    var innerCls = outer.innerCls()
    //访问内部类属性
    println(innerCls.innerField)
    innerCls.sayInnerName()
}
class Out{
var name:String = ""
class inner{
var name:String = ""
  fun info(){
        //访问外部类name属性
        this@Out.name
        //访问内部类name属性
        this.name
    }
}

}

嵌套类

嵌套类相当于Java的静态内部类,嵌套类属性外部类本身,不是外部类实例相关
嵌套类不能访问外部类的其他成员,只能访问另一个嵌套类

匿名内部类

Kotlin提供了对象表达式来表示内部类

object[:0~N个父类型]{
//对象表达式的类体部分
}
interface Outputable{
    fun a(){}
}
abstract class Product(var price:Double){
    abstract val name:String
    abstract fun proInfo()
}
fun main() {
    //创建一个父对象的对象表达式
    var ob1 = object : Outputable {
        //重写接口中的方法
        override fun a() {
            println("a 方法被重写")
        }
    }
    ob1.a()
    //创建零个父对象的对象表达式
    var ob2 = object {
        init {
            println("ob2 init")
        }
        //属性
        var name = "ob2 field"
        //方法
        fun test(){
            println("ob2 fun")
        }
    }
    ob2.test()
    //创建两个父类型的对象表达式
    val ob3 = object : Outputable,Product(33.3) {
        override val name: String = "ob3 name"

        override fun proInfo() {
            println("ob3 proInfo")
        }
    }
    ob3.proInfo()
}

对象声明和单例模式

对象声明的语法格式如下:

object ObjectName[:0~N个父类型]{
//对象表达式的类体部分
}

枚举类

Kotlin使用enum class关键字组合定义枚举类。枚举类是一种特殊的类,它一样可以有自己的属性、方法,可以实现一个或多个接口,也可以定义自己的构造器

委托

上一篇 下一篇

猜你喜欢

热点阅读