Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Design patterns 如何将类的实例与接口类型进行比较?_Design Patterns_Kotlin_Inversion Of Control_Service Locator - Fatal编程技术网

Design patterns 如何将类的实例与接口类型进行比较?

Design patterns 如何将类的实例与接口类型进行比较?,design-patterns,kotlin,inversion-of-control,service-locator,Design Patterns,Kotlin,Inversion Of Control,Service Locator,我试图在Kotlin中基于实现一个简单的服务定位器,但我想使用泛型类型参数。我还试图避免使用具体化的类型参数内联函数,因为这要求所有内容都是公共的 此类负责缓存定位服务的实例: class Cache { private val services: MutableList<Any> = mutableListOf() fun <T> getService(serviceClass: Class<T>): T? { val se

我试图在Kotlin中基于实现一个简单的服务定位器,但我想使用泛型类型参数。我还试图避免使用具体化的类型参数内联函数,因为这要求所有内容都是公共的

此类负责缓存定位服务的实例:

class Cache {
    private val services: MutableList<Any> = mutableListOf()

    fun <T> getService(serviceClass: Class<T>): T? {
        val service = services.firstOrNull { s -> s::class.java == serviceClass }

        if (service != null) {
            return service as T
        }

        return null
    }

    fun addService(service: Any) {
        services.add(service)
    }
}
无论是否包含
MyService
的实例,它每次都返回null。问题出在
s::class.java==serviceClass
,因为在运行时缓存包含一个实例
MyService
,而
MyService::class.java
并不等同于
IMyService::class
(也不是
MyService::class
,我也试过了)

我试图修改
getService
方法,如下所示:

fun <T> getService(): T? {
    val service = services.firstOrNull { s -> s is T }

    if (service != null) {
        return service as T
    }

    return null
}
fun getService():T?{
val service=services.firstOrNull{s->s是T}
if(服务!=null){
返回服务为T
}
返回空
}

s is T
上,编译器抱怨“无法检查已擦除类型:T的实例”。在没有内联的情况下,如何才能使这项工作正常进行?内联需要公开服务列表?

如果您对反射没有意见,可以使用检查请求的
类是否是缓存的给定
类的超类/超接口:

fun <T> getService(serviceClass: Class<T>): T? {
    return services.firstOrNull { s -> serviceClass.isAssignableFrom(s::class.java) } as T?
}
fun-getService(serviceClass:Class):T?{
返回services.firstOrNull{s->serviceClass.isAssignableFrom(s::class.java)}作为T?
}

为了回答关于内联的另一半问题,您可以通过使用
@PublishedApi
注释并标记字段
internal
来避免将服务映射公开。例如:

class Cache {
    @PublishedApi internal val services: MutableList<Any> = mutableListOf()

    inline fun <reified T> getService(serviceClass: Class<T>): T? {
        return T::class.java.let { it.cast(services.firstOrNull(it::isInstance)) }
    }

    fun addService(service: Any) {
        services.add(service)
    }
}
类缓存{
@PublishDAPI内部val服务:MutableList=mutableListOf()
内联服务(serviceClass:Class):T{
返回T::class.java.let{it.cast(services.firstOrNull(it::isInstance))}
}
乐趣添加服务(服务:任何){
服务。添加(服务)
}
}

多亏了KCopock的好主意,您可以使用的注释
也是
,避免了反射并使函数非常简洁:

class Cache {
    @PublishedApi internal val services: MutableList<Any> = mutableListOf()

    inline fun <reified T> getService() = services.firstOrNull { it is T } as T?

    // ...
}
类缓存{
@PublishDAPI内部val服务:MutableList=mutableListOf()
inline fun getService()=services.firstOrNull{it is T}作为T?
// ...
}

如果您想保持
服务的私有性(或使
getService
在Java中可用),并且仍然保持Kotlin更好的可用性,只需添加一个重载:

fun <T> getService(serviceClass: Class<T>): T? { ... }

inline fun <reified T> getService(): T? = getService(T::class.java)
fun-getService(serviceClass:Class):T?{ ... }
内联趣味getService():T?=getService(T::class.java)

或者
serviceClass.isInstance也会做同样的事情。在这种情况下,我有什么理由想避免反射吗?我不认为这里比其他任何地方都有更多的理由避免反射,如果你不使用reified,这就是方法。有些人只是出于各种原因而避免反思。
fun <T> getService(serviceClass: Class<T>): T? { ... }

inline fun <reified T> getService(): T? = getService(T::class.java)