我有一个抽象类,某个包中的所有类都从该类派生。在Android上使用Kotlin时,是否可以创建一种列表来动态实例化驻留在某个程序包中的所有这些类?
这里是一个例子:
com.example.service.emailservice中的所有类均派生自com.example.service中的BaseService抽象类。我想创建一个包含GmailService和OutlookService对象的列表。我可以手动实例化它们并将它们添加到列表中,但是将来我可以添加新服务,例如YandexService,它也应该出现在列表中。这需要再次手动实例化。有没有一种方法可以自动实例化某些程序包中的类?
答案 0 :(得分:0)
使用this library
添加到gradle.build
implementation 'org.reflections:reflections:0.9.11'
然后在您的软件包com.example.service
中创建一个类,从中创建服务,将其称为ServiceFactory
,这里是实现:
package com.example.service
import org.reflections.Reflections
class ServiceFactory {
init {
val reflections = Reflections(javaClass.`package`.name)
val subTypes = reflections.getSubTypesOf(BaseService::class.java)
val yourServices = subTypes.map { it.getConstructor().newInstance() }
yourServices.forEach { println(it.javaClass.name) }
}
}
fun main() {
ServiceFactory()
}
退出:
com.example.service.emailservice.OutlookService
com.example.service.emailservice.GmailService
您正在寻找的东西吗?
编辑:当然,您可以从其他位置实例化此服务,但是在这种情况下,您需要对Reflections("com.example.service")
进行硬编码
答案 1 :(得分:0)
有两种市长方法。
第一个-更简单,更脏的“ Reflection”。 您可能会在Java中找到很多示例。不过,在Kotlin中并没有那么多,但是从我读过的here来看,这是不可能的。 但是,不建议在生产中使用“反射”,它通常被认为是实现某些目标的不好方法。
第二种方法是注释处理器-这种方法难度更大。但是,它被认为是执行此类任务的一种干净方法,并且它是代码生成技术的通用标准。这样,只要您下定决心,就可以做各种魔术。 Here是一篇不错的文章。
通常,我建议使用半自动方法。
例如: 在具有init方法的基本服务中
abstract class BaseService {
abstract fun init(): BaseService
}
让您所有的服务都实现此BaseService
class Service : BaseService() {
override fun init(): BaseService {
return Service()
}
}
...
然后创建一个类列表
val services = listOf(Service(), Service1(), Service2())
并初始化它们
services.forEach { it.init() }
这与您所拥有的并没有太大不同,并且可能需要对您的服务和应用程序进行整体上的逻辑和体系结构更改,但这不会很脏,也不需要大量的学习时间和时间开销。
希望有帮助。