kotlin学习笔记(三)

本文介绍了Kotlin中的面向对象编程特性,包括类的定义、继承、抽象类、密封类等概念,并通过具体示例展示了如何在Kotlin中实现这些特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

面向对象

package learn
class father(val str:String){
    val string=str;
   fun start(){
       println("${string}:kotlin")
   }
}

使用上面的father类

import learn.father

fun main(args: Array<String>) {
val father=father("hello")
    father.start()
}

结果


继承

/**
 * 定义一个父类
 */
open class father(open val str:String) {
    open fun start() {
        println("father")
    }
}
/**
 * 定义一个子类
 */
class son(override val str :String):father(str){
    override fun start()
    {
        println("son")
    }

}
main函数代码

fun main(args: Array<String>) {
    val father1: father = son("hello")
    val son = son("hello")
    val father2 = father("hello")

    father1.start()
    son.start()
    father2.start()
}

总结:kotlin的写法跟java写法有很大的不同,kotlin的继承用的是冒号,被继承的father类要在class加上open关键词才可以被继承,子类继承父类是要实现父类的构造函数。子类重写父类方法是父类方法前要加open关键词,子类方法前面要加override关键词,使用var father:father=son("son")是还是跟java一样,左边是编译,右边是运行,也就是调用start方法还是输出son;

复写规则

在 kotlin 中,实现继承通常遵循如下规则:如果一个类从它的直接父类继承了同一个成员的多个实现,那么它必须复写这个成员并且提供自己的实现(或许只是直接用了继承来的实现)。为表示使用父类中提供的方法我们用 super<Base>表示:

open class A {
	open fun f () { print("A") }
	fun a() { print("a") }
}

interface B {
	fun f() { print("B") } // 接口的成员变量默认是 open 的
	fun b() { print("b") }
}

class C() : A() , B {
	// 编译器会要求复写f()
	override fun f() {
		super<A>.f() // 调用 A.f()
		super<B>.f() // 调用 B.f()
	}
}

可以同时从 A 和 B 中继承方法,而且 C 继承 a() 或 b() 的实现没有任何问题,因为它们都只有一个实现。但是 f() 有俩个实现,因此我们在 C 中必须复写 f() 并且提供自己的实现来消除歧义。

抽象类

一个类或一些成员可能被声明成 abstract 。一个抽象方法在它的类中没有实现方法。记住我们不用给一个抽象类或函数添加 open 注解,它默认是带着的。

我们可以用一个抽象成员去复写一个带 open 注解的非抽象方法。

open class Base {
	open fun f() {}
}

abstract class Derived : Base() {
	override abstract fun f()
}

伴随对象

在 kotlin 中不像 java 或者 C# 它没有静态方法。在大多数情形下,我们建议只用包级别的函数。

如果你要写一个没有实例类就可以调用的方法,但需要访问到类内部(比如说一个工厂方法),你可以把它写成它所在类的一个成员(you can write it as a member of an object declaration inside that class)

更高效的方法是,你可以在你的类中声明一个伴随对象,这样你就可以像 java/c# 那样把它当做静态方法调用,只需要它的类名做一个识别就好了

密封类

密封类用于代表严格的类结构,值只能是有限集合中的某中类型,不可以是任何其它类型。这就相当于一个枚举类的扩展:枚举值集合的类型是严格限制的,但每个枚举常量只有一个实例,而密封类的子类可以有包含不同状态的多个实例。

声明密封类需要在 class 前加一个 sealed 修饰符。密封类可以有子类但必须全部嵌套在密封类声明内部、

sealed class Expr {
	class Const(val number: Double) : Expr()
	class Sum(val e1: Expr, val e2: Expr) : Expr()
	object NotANumber : Expr()
}

注意密封类子类的扩展可以在任何地方,不必在密封类声明内部进行。

使用密封类的最主要的的好处体现在你使用 when 表达式。可以确保声明可以覆盖到所有的情形,不需要再使用 else 情形。

fun eval(expr: Expr): Double = when(expr) {
	is Const -> expr.number
	is Sum -> eval(expr.e1) + eval(expr.e2)
	NotANumber -> Double.NaN
    // the `else` clause is not required because we've covered all the cases
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值