Search code examples
androidperformancekotlingeneric-programming

Create method with generic parameter for repeated actions


I have the following methods on my code:

fun saveArticles(data: JSONArray) {
    var active = String()
    for (i in 0..data.length().minus(1)) // create string

    val articles = Select.from(Article::class.java).list()

    val iterator = articles.iterator()
    while (iterator.hasNext()) {
        val article = iterator.next() as Article
        if (!active.contains(Regex(article.id.toString()))) article.delete()
    }
}

fun saveDossiers(data: JSONArray) {
    var active = String()
    for (i in 0..data.length().minus(1)) // create string

    val dossiers = Select.from(Dossier::class.java).list()

    val iterator = dossiers.iterator()
    while (iterator.hasNext()) {
        val dossier = iterator.next() as Dossier
        if (!active.contains(Regex(dossier.id.toString()))) dossier.delete()
    }
}

fun saveVideos(data: JSONArray) {
    var active = String()
    for (i in 0..data.length().minus(1)) // create string

    val videos = Select.from(Video::class.java).list()

    val iterator = videos.iterator()
    while (iterator.hasNext()) {
        val video = iterator.next() as Video
        if (!active.contains(Regex(video.id.toString()))) video.delete()
    }
}

As you can see, all the methods do exactly the same thing. The only difference is the Class type of the object I'm working at the moment. Can I somehow create a single method with a parameter of Class type, and depending of the type change the class I need to work? Something like this:

fun saveVideos(data: JSONArray, type: Class) {
    var active = String()
    for (i in 0..data.length().minus(1)) // create string

    val list = Select.from(type).list()

    val iterator = list.iterator()
    while (iterator.hasNext()) {
        val item = iterator.next() as type
        if (!active.contains(Regex((item as type).id.toString()))) item.delete()
    }
}

Solution

  • You need to extract an interface and use a reified generic.

    interface Blabla {
        fun delete()
        val id: Int
    }
    
    inline fun <reified T : Blabla>saveVideos(data: JSONArray) {
        var active = String()
        for (i in 0..data.length().minus(1)) // create string
    
        val list = Select.from(T::class.java).list()
    
        val iterator = list.iterator()
        while (iterator.hasNext()) {
            val item = iterator.next() as T
            if (Regex(item.id.toString()) !in active) item.delete()
        }
    }
    

    This should work.

    Also, I highly recommend you to use the Kotlin collection library, like this.

    inline fun <reified T : Blabla>saveVideos(data: JSONArray) {
        val active = ""
        for (i in 0 until data.length()) {} // create string
    
        val list = Select.from(T::class.java).list()
    
        list
                .map { it as T }
                .filter { Regex(it.id.toString()) !in active }
                .forEach { it.delete() }
    }
    

    And you can even replace forEach { it.delete() } with forEach(T::delete)