【Android】Kotlin教程(6)

news/2024/11/1 5:45:38/

文章目录

      • 1.接口
      • 2.抽象类
      • 3.泛型类
      • 4.泛型函数
      • 5.多泛型参数
      • 6.out和int
      • 7.reified
      • 8.定义扩展函数
      • 9.扩展属性
      • 10.泛型扩展函数

1.接口

Kotlin 的接口可以既包含抽象方法的声明也包含实现。与抽象类不同的是,接口无法保存状态。它可以有属性但必须声明为抽象或提供访问器实现。

kotlin">interface MyInterface {fun bar()fun foo() {// 可选的方法体}
}
kotlin">interface Moveable {var maxSpeed: Intvar wheels: Intfun move(moveable: Moveable): String
}class Car(private val name: String,override var wheels: Int = 4,override var maxSpeed: Int = 100
) : Moveable {override fun move(moveable: Moveable): String {return "${moveable.javaClass.simpleName} with name $name is moving"}override fun toString(): String {return "Car(name=$name, wheels=$wheels, maxSpeed=$maxSpeed)"}
}fun main() {val car = Car("xiaomi")println(car.move(car))
}

2.抽象类

抽象类是一种不能被实例化的类,它主要用于定义一组通用的行为和属性,这些行为和属性可以被其子类继承。抽象类可以包含抽象方法(没有实现的方法)以及具体的实现方法。子类必须提供抽象方法的具体实现,除非子类本身也是抽象的。

kotlin">// 定义一个抽象类
abstract class Animals {// 抽象属性abstract val image: String// 抽象方法abstract fun makeSound()// 具体方法open fun breathe() {println("呼吸")}// 构造函数constructor(name: String) {println("动物的名字是 $name")}
}// 实现抽象类
class Dog : Animals("狗") {override val image = "dog.jpg"override fun makeSound() {println("汪汪!")}
}class Cat : Animals("猫") {override val image = "cat.jpg"override fun makeSound() {println("喵喵!")}
}fun main() {val dog = Dog()dog.makeSound()  // 输出: 汪汪!dog.breathe()    // 输出: 呼吸val cat = Cat()cat.makeSound()  // 输出: 喵喵!cat.breathe()    // 输出: 呼吸
}

3.泛型类

泛型类的构造函数可以接受任何类型。

kotlin">class MagicBox<T>(val item: T) {private var subject : T = itemfun open() : String {return "subject -- $subject."}
}class Boy(val name : String, val age : Int)class Tiger(val weight: Int)fun main() {val  box1:MagicBox<Boy> = MagicBox(Boy("tony",10))val  box2:MagicBox<Tiger> = MagicBox(Tiger(100))println(box1.open()) // subject -- Boy@27716f4.println(box2.open()) // subject -- Boy@27716f4.
}

4.泛型函数

泛型参数也可以用于函数

kotlin">class MagicBox<T>(val item: T) {private var subject : T = itemfun open() : String {return "subject -- $subject."}fun call() : T {return subject}
}class Boy(val name : String, val age : Int)class Tiger(val weight: Int)fun main() {val  box1:MagicBox<Boy> = MagicBox(Boy("tony",10))val  box2:MagicBox<Tiger> = MagicBox(Tiger(100))println(box1.open()) // subject -- Boy@27716f4.println(box2.open()) // subject -- Boy@27716f4.println(box1.call()) // Boy@27716f4println(box2.call()) // Tiger@8efb846
}

5.多泛型参数

泛型函数或泛型类也可以有多个泛型参数。

定义多泛型参数的类

kotlin">class Pair<T, U> (val first: T, val second: U) {fun printPair() {println("First: $first, Second: $second")}
}fun main() {val pair = Pair(1, "one")pair.printPair()  // 输出: First: 1, Second: one
}

定义多泛型参数的接口

kotlin">interface Container<K, V> {fun put(key: K, value: V)fun get(key: K): V?
}class HashMapContainer<K, V> : Container<K, V> {private val map = mutableMapOf<K, V>()override fun put(key: K, value: V) {map[key] = value}override fun get(key: K): V? {return map[key]}
}fun main() {val container: Container<String, Int> = HashMapContainer()container.put("key1", 100)println(container.get("key1"))  // 输出: 100
}

多泛型参数的函数

kotlin">fun <T, U> combine(first: T, second: U): Pair<T, U> {return Pair(first, second)
}fun main() {val result = combine(42, "answer")println(result)  // 输出: Pair(first=42, second=answer)
}

泛型约束:你可能希望对泛型参数进行一些限制,例如要求它们必须实现某个特定的接口。这可以通过类型约束来实现:

kotlin">fun <T : Comparable<T>> findMax(a: T, b: T): T {return if (a > b) a else b
}fun main() {val maxInt = findMax(3, 5)println(maxInt)  // 输出: 5val maxString = findMax("apple", "banana")println(maxString)  // 输出: banana
}

在这个例子中,findMax 函数的类型参数 T 被限制为实现了 Comparable 接口的类型,这样就可以使用比较运算符。

6.out和int

out关键字用于实现协变(covariance),这允许你在泛型类型参数上定义一种更灵活的类型关系。协变主要用于处理只读操作,比如从集合中获取元素,而不涉及写入或修改这些元素的操作。

协变是指当一个类型 A 是类型 B 的子类型时,那么 List<A> 也可以被视为List<B>的子类型。这种关系使得我们可以使用更通用的类型来引用具体的子类型实例。

逆变是指当一个类型 A 是类型 B 的子类型时,那么 Consumer<A> 也可以被视为 Consumer<B> 的子类型。这种关系使得我们可以使用更通用的类型来引用具体的子类型实例,但方向是相反的。

  • 父类泛型对象可以赋值给子类泛型对象,用in
  • 子类泛型对象可以赋值给父类泛型对象,用out
kotlin">// out
interface Production<out T>{fun produce() : T
}// in
interface Consumer<in T>{fun consume(t : T)
}// 不变
interface ProductionConsumer<T> {fun product() : Tfun consume(item : T)
}open class Foodopen class FastFood : Food()class Burger : FastFood()// 生产者
// 食品商店
class FoodStore : Production<Food>{override fun produce(): Food{println("Produce Food.")return Food()}
}class FastFoodStore : Production<FastFood>{override fun produce(): FastFood{println("Produce FastFood.")return FastFood()}
}class BurgerStore : Production<Burger>{override fun produce(): Burger{println("Produce Burger.")return Burger()}
}class FoodConsumer : Consumer<Food>{override fun consume(item: Food) {println("Consume Food.")}
}class FastFoodConsumer : Consumer<FastFood>{override fun consume(item: FastFood) {println("Consume FastFood.")}
}class BurgerConsumer : Consumer<Burger>{override fun consume(item: Burger) {println("Consume Burger.")}
}
fun main() {val production1 : Production<Food> = FoodStore()val production2 : Production<Food> = FastFoodStore()val production3 : Production<Food> = BurgerStore()val consumer1 : Consumer<Food> = FoodConsumer()val consumer2 : Consumer<FastFood> = FoodConsumer()val consumer3 : Consumer<Burger> = FoodConsumer()
}

7.reified

reified 是一个关键字,用于使类型参数在运行时具体化。通常情况下,泛型的类型信息在编译后会被擦除(即类型擦除),这意味着你不能在运行时获取到具体的类型信息。然而,通过使用 reified 关键字,Kotlin 允许你在某些上下文中保留这些类型信息。

kotlin">// 定义一个泛型类 MagicBox2,泛型 T 必须是 Human 的子类
class MagicBox2<T : Human> {// 定义一个内联泛型方法 randomOrBackup,使用 reified 关键字使 T 类型在运行时可用inline fun <reified T> randomOrBackup(backup: () -> T): T {// 创建一个包含不同类型 Human 对象的列表val items = listOf(Man("C++", 40),Feman("Kotlin", 45))// 随机打乱列表并取第一个元素val randomItem = items.shuffled().first()// 如果随机选中的元素是 T 类型,则返回该元素;否则调用备份函数返回一个默认值return if (randomItem is T) {randomItem} else {backup()}}
}// 定义一个开放类 Human,包含一个年龄属性
open class Human(val age: Int)// 定义一个 Man 类,继承自 Human,包含一个姓名属性
class Man(val name: String, age: Int) : Human(age)// 定义一个 Feman 类,继承自 Human,包含一个姓名属性
class Feman(val name: String, age: Int) : Human(age)fun main() {// 创建一个 MagicBox2 实例,指定泛型为 Manval magicBox = MagicBox2<Man>()// 调用 randomOrBackup 方法,如果随机选中的不是 Man 类型,则返回一个 Feman 对象作为备份val man = magicBox.randomOrBackup {Feman("Java", 35)}// 打印结果,输出选中的对象的姓名println(man.name)
}

8.定义扩展函数

扩展函数允许你为现有的类添加新的功能,而无需修改该类的源代码。这使得你可以向库中的类或第三方库中的类添加自定义方法,从而增强其功能。扩展函数在使用时看起来就像它们是原始类的一部分一样。

定义扩展函数:要定义一个扩展函数,你需要在函数名前面指定接收者类型(即你要扩展的类),并在接收者类型和函数名之间使用点号 .。接收者类型的实例将作为隐式的第一个参数传递给扩展函数。

String 类添加一个扩展函数来检查字符串是否是回文:

kotlin">fun String.isPalindrome(): Boolean {return this == this.reversed()
}fun MutableList<Int>.swap(index1: Int, index2: Int) {val tmp = this[index1] // “this”对应该列表this[index1] = this[index2]this[index2] = tmp
}fun main() {val str = "madam"println(str.isPalindrome())  // 输出: trueval list = mutableListOf(1, 2)list.swap(0, 1)println(list)  // 输出: [2, 1]
}

9.扩展属性

除了扩展函数,Kotlin 还支持扩展属性。扩展属性与扩展函数类似,但用于定义新的属性。

kotlin">// 示例
val String.firstChar: Char?get() = if (this.isEmpty()) null else this[0]fun main() {val str = "hello"println(str.firstChar)  // 输出: h
}

10.泛型扩展函数

kotlin">class Box<T>(val item: T)// 为 Box<T> 添加一个扩展函数
fun <T> Box<T>.printItem() {println("The item in the box is: $item")
}fun main() {val intBox = Box(42)intBox.printItem()  // 输出: The item in the box is: 42val stringBox = Box("Hello, World!")stringBox.printItem()  // 输出: The item in the box is: Hello, World!
}

http://www.ppmy.cn/news/1543503.html

相关文章

鸿蒙生态给我们带来的机遇和挑战

鸿蒙系统不断发展&#xff0c;有与安卓、iOS 形成三足鼎立之势&#xff0c;且其在智能手机、智能穿戴、车载、家居等行业领域的应用越来越广泛。作为开发者&#xff0c;如何抓住鸿蒙生态崛起的机遇&#xff0c;解决开发挑战&#xff0c;创造更好的应用体验&#xff1f; 一、阐…

前端SSE-EventSource message事件执行异常问题

前端SSE-EventSource message事件执行异常问题 前言&#xff1a; 最近项目中需要做一个消息中心-需要实现实时推送消息到客户端&#xff0c;之前一直都是使用WebSocket&#xff0c;但是最近了解到有比它更轻量化的方法可以达到相同的效果&#xff0c;就是SSE。但是与后端进行联…

JAVA开发入门

Java 是一种广泛使用的面向对象编程语言&#xff0c;它以其“一次编写&#xff0c;到处运行”&#xff08;Write Once, Run Anywhere, WORA&#xff09;的特点而闻名。Java 被设计为能够在任何支持 Java 的平台上运行&#xff0c;这主要得益于 Java 虚拟机&#xff08;JVM&…

图文展示如何在github上贡献合并请求

大致步骤为&#xff1a; 登录github -> 打开目标仓库 -> 点击fork按钮 -> 复制分叉出来的新仓库地址 -> 克隆到本地 -> 修改代码后提交 -> 网页上点击Contribute -> 弹窗里点击Open pull request -> 跳转出来的新页面里点击Create pull request 详细…

Spring Boot技术在校园社团管理中的高效应用

3系统分析 3.1可行性分析 通过对本校园社团信息管理系统实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本校园社团信息管理系统采用SSM框架&#xff0c;JAVA作…

数对的最大曼哈顿距离[ABC178E] Dist Max

[ABC178E] Dist Max 题面翻译 给定平面上 N N N 个点&#xff0c;求出所有点对间的最大曼哈顿距离。 题目描述 二次元平面上に $ N $ 個の点があり、$ i $ 番目の点の座標は $ (x_i,y_i) $ です。 同じ座標に複数の点があることもあります。 異なる二点間のマンハッタン距…

[前端面试]计算机网络

TCP/IP 与OSI TCP/IP TCP/IP 四层模型是一个分层网络通信模型&#xff0c; 它将网络通信过程分为四个层次&#xff0c;这四层分别是&#xff1a;网络接口层、互联网层、传输层和应用层。 网络接口层负责在计算机和网络硬件之间传输数据&#xff0c;负责在物理网络上发送和接…

ubuntu用户账号相关操作

用户账号相关 查看当前登录用户 可以使用 who 或 w 命令来查看当前登录到系统的用户。这些命令会列出当前登录用户的用户名以及登录的时间和终端信息。以下是示例&#xff1a; who或者 w这些命令的输出可能会像这样&#xff1a; user1 pts/0 2024-04-20 09:30 (:0) user…