Android 通用科特林工厂未经检查的铸件

Android 通用科特林工厂未经检查的铸件,android,generics,kotlin,Android,Generics,Kotlin,我试图在kotlin中创建一个通用工厂,用于将一些字符串解析为模型类: internal interface Model data class UserId(val id: String, val name: String, val link: String): Model data class Shelf(val id: String, val name: String, val bookCount: Int): Model internal inline fun <reified

我试图在kotlin中创建一个通用工厂,用于将一些字符串解析为模型类:

internal interface Model

data class UserId(val id: String, val name: String, val link: String): Model
data class Shelf(val id: String, val name: String, val bookCount: Int): Model

internal inline fun <reified T: Model> getParser(): Parser<T> {
    return when (T::class) {
            UserId::class -> UserIdParser() as Parser<T>
            Shelf::class -> UserShelvesParser() as Parser<T>
            else -> throw Exception("can't match proper parser")
        }
}

internal interface Parser<out T: Model> {
    fun parse(xml: String): T
}


internal class UserIdParser : Parser<UserId> {
    override fun parse(xml: String): UserId {
        return parseUserId(xml)
    }
}

internal class UserShelvesParser : Parser<Shelf> {
    override fun parse(xml: String): Shelf {
        return parseShelf(xml)
    }
}
// for example
internal fun parseUserId(xml: String) = UserId("123", "owl", "ya.ru")
internal fun parseShelf(xml: String) = Shelf("123", "to-read", 20)
内部接口模型
数据类UserId(val-id:String,val-name:String,val-link:String):模型
数据类工具架(val id:String,val name:String,val bookCount:Int):模型
内部内联语法分析器():语法分析器{
返回时间(T::class){
UserId::class->UserIdParser()作为解析器
Shelf::class->UserShelvesParser()作为解析器
else->抛出异常(“无法匹配正确的解析器”)
}
}
内部接口解析器{
有趣的解析(xml:String):T
}
内部类UserIdParser:解析器{
重写有趣的解析(xml:String):UserId{
返回parseUserId(xml)
}
}
内部类UserShelvesParser:Parser{
重写有趣的解析(xml:String):Shelf{
返回parseShelf(xml)
}
}
//比如说
内部用户id(xml:String)=用户id(“123”、“owl”、“ya.ru”)
内部工具架(xml:String)=工具架(“123”,“待读”,20)
因此,在客户端代码中,我可以编写以下代码:

val t = getParser<UserId>().parse("")
val t=getParser().parse(“”)

它可以工作,但在
getParser
方法中,我得到了警告
未选中的从UserIdParser到Parser的强制转换。如果没有惯用的警告,我怎么能在kotlin中实现这样的行为呢

这与您的目标略有不同,但它在没有任何警告的情况下工作:

internal interface Model

data class UserId(val id: String, val name: String, val link: String) : Model
data class Shelf(val id: String, val name: String, val bookCount: Int) : Model

internal inline fun <reified T : Model> parse(xml: String) = when (T::class) {
    UserId::class -> parseUserId(xml)
    Shelf::class -> parseShelf(xml)
    else -> throw Exception("can't match proper parser")
} as T

// for example
internal fun parseUserId(xml: String) = UserId("123", "owl", "ya.ru")

internal fun parseShelf(xml: String) = Shelf("123", "to-read", 20)
内部接口模型
数据类UserId(val-id:String,val-name:String,val-link:String):模型
数据类工具架(val id:String,val name:String,val bookCount:Int):模型
内部内联fun解析(xml:String)=何时(T::class){
UserId::class->parseUserId(xml)
Shelf::class->parseShelf(xml)
else->抛出异常(“无法匹配正确的解析器”)
}as T
//比如说
内部用户id(xml:String)=用户id(“123”、“owl”、“ya.ru”)
内部工具架(xml:String)=工具架(“123”,“待读”,20)
那么它可以这样叫:

val t = parse<UserId>("")
val t=parse(“”)

希望这能对您有所帮助。

我不确定您是否必须在when语句中将
转换为解析器
,因为
UserIdParser
UserShelvesParser
已经在扩展
解析器
。这样,类型是精确的,不会试图猜测
T
Parser
中是什么,我得到了类型不匹配错误:必需的解析器和find UserIdParser。这也不起作用,因为它是具体化的泛型类型param,而不是某个类的实例-T不是表达式当
块时,您可以将强制转换移到
块之外-因此您将只有一个警告而不是两个。是的)但这降低了门槛)我想知道如果有任何方法可以在没有警告的情况下表达这个简单的概念,那么如果你这样写的话,警告就会消失,但是你返回的是基本模型类型,而不是子具体类型,比如UserId或Shelf,然后客户端应该转换到一个适当的具体类,这有点让整个想法变得有用我编辑了我的答案,在when语句之后添加一个cast,它现在返回具体类型。非常感谢-这很有效!很明显,问题出在诸如Parser之类的嵌套泛型类型上,编译器可能无法推断这些类型,但经过简化,仅t,所有这些都可以解决。