Kotlin vararg of A to vararg of B

2019-08-26 06:20发布

问题:

I am trying to implement a Filter class that can be composed of other Filter classes.The goal is that each filter can process an object and return a boolean, and if it is made of several filters it computes the AND of all its filters.

I am trying to get one of the constructors to take a vararg of predicates, which needs to be converted into a vararg of Filters. The compiler says that none of the functions (the primary and first secondary constructors) can be called with these parameters.

My understanding is that * should convert List<Filter<T>> into vararg Filter<T>, but it is not working.

class Filter<in T>(private vararg val filters: Filter<T>) {
    constructor(predicate: (T) -> Boolean) : this(Filter(predicate))
    constructor(vararg predicates: (T) -> Boolean) : this(Filter<T>(*(predicates.map { predicate -> Filter<T>(predicate) })))

    fun process(input: T): Boolean {
        for (filter in filters) { if (!filter.process(input)) return false }
        return true
    }
}

What can I do to achieve that?

Also, is it a big overhead iterating over filters of just one predicate compared to just checking the predicate (considering this will be called a lot of times, to filter a list)?

回答1:

No '*' is the spread opperator and can be used on array to be passed as vararg parameter. You will need to change your last constructor to:

constructor(vararg predicates: (T) -> Boolean) : this(*predicates.map { Filter(it) }.toTypedArray())

predicates is map to a list of Filter and then the list is converted to an array and passed as vararg using the spread operator.

Note that you don't need to specify any type because the compiler can infer thoses types.