IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> kotlin 泛型 -> 正文阅读

[移动开发]kotlin 泛型

一、泛型使用

????????泛型,即 "参数化类型",将类型参数化,可以用在类,接口,函数上。

????????与 Java 一样,Kotlin?也提供泛型,为类型安全提供保证,消除类型强转的烦恼。

1.1 泛型的优点
类型安全:通用允许仅保留单一类型的对象。泛型不允许存储其他对象。

不需要类型转换:不需要对对象进行类型转换。

编译时间检查:在编译时检查泛型代码,以便在运行时避免任何问题。

1.2 泛型类
? ? ? ? TFood类指定的泛型参数由放在一对<>里的字母T表示,T是个代表item类型的占位符。TFood类接受任何类型的item作为主构造函数值(item: T)。

//1、创建泛型类
class TFood<T>(item:T) {
    init {
        println(if(item is TApple){(item as? TApple)?.price}else item)
    }


}

//2、创建传入的类
class TApple(var price :Int)



//3、使用
fun main() {
    //传入Int类型
    TFood(30)//30
    //传入String类型
    TFood("水果")//水果
    //传入实体对象
    TFood(TApple(13))//13
}

1.3 泛型函数

泛型参数也可以用于函数。

定义一个函数用于获取元素,当且仅当泛型类可用时,才能获取元素。

1.4 泛型接口


?

interface IFoodEffect<T>{
? ? fun effect(item:T)
}
//实现接口
class Banana:IFoodEffect<String>{
? ? override fun effect(item: String) {
? ? ? ? println(item)//item
? ? }
?
}
? ? //使用
? ? Banana().effect("常食香蕉有益于大脑,预防神经疲劳,还有润肺止咳、防止便秘")

二、泛型类型约束
指定参数类型:我想让这个泛型类只能传入某种类型。

open class Vip(price:Int)
?
class TApple(var price: Int): Vip(price)
class TFood<T:Vip>(item: T) {
? ? ...
}


? T:Vip,这样写就表示这里只能传入Vip和其子类。这个就类似Java的 <? extends T> 上界通配符
?

三、形变

  • out(协变):它只能出现在函数的输出位置,只能作为返回类型,即生产者

  • in(逆变):它只能出现在函数的输入位置,作为参数,只能作为消费类型,即消费者。

  • 默认(不变):如果泛型类既将泛型类型作为函数参数,又将泛型类型作为函数的输出,那么既不用out也不用in。

3.1 不变

????????泛型类型即作为输出又作为参数。

/**
 * 泛型接口  不变
 */
interface IUnchanged<T> {
    fun originally():T
    fun originally(item:T)

}
class BigStore:IUnchanged<String>{
    override fun originally(): String {
        return "实现泛型接口  不变---返回类型"
    }

    override fun originally(item: String) {
       println("------------不变---传参 ---=="+item)
    }
}

fun main() {
    println("---------------实现泛型接口------- 不变 默认---------------")
    var iUnchanged=BigStore()
    println(iUnchanged.originally())
    println(iUnchanged.originally("参数"))
}

3.2 out-协变

????????它只能出现在函数的输出位置,只能作为返回类型,即生产者

????????作用:可以将子类泛型对象可以赋值给父类泛型对象

//out
interface IReturn<out T>{
    fun effect():T
}
 
open class Fruit()
class AppleHn():Fruit()
 
//生产者
class FruitMarket:IReturn<Fruit>{
    override fun effect(): Fruit {
        println("FruitMarket effect")
        return Fruit()
    }
}
class AppleHnMarket:IReturn<AppleHn>{
    override fun effect(): AppleHn {
        println("AppleHnMarket effect")
        return AppleHn()
    }
}
 
fun main() {
    //out:可以将子类泛型对象(AppleHn)可以赋值给父类泛型对象(Fruit)
    var fm:IProduction<Fruit> = FruitMarket()
    println(fm.effect())
    //am的引用类型是Fruit对象
    //但是AppleHnMarket返回的是AppleHn对象。
    //这里将AppleHn对象赋值给Fruit对象并返回。
    var am:IProduction<Fruit> = AppleHnMarket()
    println(am.effect())
}
 

3.3 in-逆变

????????它只能出现在函数的输入位置,只能作为参数,即消费者

????????作用:可以将父类泛型对象可以赋值给子类泛型对象

//in
interface IConsumer<in T>{
    fun spend(t:T)
}
 
class Animal:IConsumer<Fruit>{
    override fun spend(t: Fruit) {
        println("Animal spend Fruit")
    }
}
 
class People:IConsumer<AppleHn>{
    override fun spend(t: AppleHn) {
        println("People spend AppleHn")
    }
}
fun main() {
    //in:可以将父类泛型对象(Fruit)可以赋值给子类泛型对象(AppleHn)
    var fca: IConsumer<AppleHn> = Animal()
    fca.spend(AppleHn())
    println(fca)
    var fcp: IConsumer<AppleHn> = People()
    fcp.spend(AppleHn())
    println(fcp)
}

五、vararg
? ? ? ? 泛型类一次只能放一个,如果需要放入多个实例呢?

class BookMany<T : AndroidMany>(vararg item: T) {
? ? var data: Array<out T> = item
}
?
open class AndroidMany(name: String)
class KotlinMany(var name: String, var price: Int) : AndroidMany(name) {
? ? override fun toString(): String {
? ? ? ? return "KotlinS(name='$name', price=$price)"
? ? }
}
?
class JavaMany(var name: String, var price: Int) : AndroidMany(name) {
? ? override fun toString(): String {
? ? ? ? return "JavaS(name='$name', price=$price)"
? ? }
}
?
fun main() {
? ? var book = BookMany(
? ? ? ? KotlinMany("初学者", 18),
? ? ? ? KotlinMany("进阶者", 28),
? ? ? ? KotlinMany("终结者", 38),
? ? ? ? JavaMany("全面者", 35),
? ? )
? ? println(book)//com.scc.kotlin.primary.classkotlin.BookMany@3d24753a
}
?


? ? ? ? 添加完多个对象,如果直接打印book,那么获取到的是个BookMany对象,那么怎么获取book里面的的对象?

重载运算符函数get函数,通过[]操作符取值。

class BookMany<T : AndroidMany>(vararg item: T) {
? ? var data: Array<out T> = item
? ? operator fun get(index:Int) = data[index]
}
?
fun main() {
? ? var book = BookMany(
? ? ? ? KotlinMany("初学者", 18),
? ? ? ? KotlinMany("进阶者", 28),
? ? ? ? KotlinMany("终结者", 38),
? ? ? ? JavaMany("全面者", 35),
? ? )
? ? println(book)//com.scc.kotlin.primary.classkotlin.BookMany@3d24753a
? ? println(book[0])//KotlinS(name='初学者', price=18)
? ? println(book[2])//KotlinS(name='终结者', price=38)
}

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-09-24 21:08:24  更:2022-09-24 21:09:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 5:31:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码