передать список интерфейса, который используется в классе для конструктора - PullRequest
2 голосов
/ 13 июня 2019

У меня есть два интерфейса, которые имеют 2 разные переменные.Я создал класс, который реализует эти 2 интерфейса.Теперь я хочу передать список первого интерфейса конструктору другого класса и использовать его свойство (из обоих интерфейсов).Пока мне удалось получить конструктор, но я не смог найти, как передать список параметров

interface A {
    var name: String
}

interface B {
    var job: String
}

class C(
    override var name: String,
    override var job: String
) : A, B

class D() {
    private fun getList() {
        val list: List<A> = arrayListOf(
            C("user1", "job1"),
            C("user2", "job2"),
            C("user3", "job3")
        )
        // I want to init E() my constructor here 
    }
}

class E<T>(val list: List<T>) where T : A, T: B {
    fun display() {
        list.forEach {
            println("my name is ${list.get(i).name} and I am a ${list.get(i).job}")
        }
    }
}

Ответы [ 2 ]

2 голосов
/ 13 июня 2019

Немного расширяю ответ, который дал @Scrobot.

В короткие сроки вы не можете делать то, что пытаетесь сделать. Когда вы указываете List<A> в качестве типа, вы пропускаете информацию о том, реализует ли элементы в вашем списке интерфейс B.

Если бы вы могли делать то, что пытались сделать, вы могли бы очень легко взломать ваш код, выполнив такие действия:

class PureA : A {
    override var name: String
}

val list: List<A> = arrayListOf(
    C("user1", "job"),
    PureA("user2")
)

// The following line will not work, and for good reason
// E(list)

Если бы сработала последняя строка, вы бы просто сломали свой код. PureA является допустимым элементом в списке As, но не относится к E.

Следующее намного ближе к тому, что вы собираетесь делать:

// Doesn't work fully
class D<T> where T: A, T: B {
    private fun getList(): E<T> {
        val list: List<T> = arrayListOf<T>(
            C("user1", "job1"),
            C("user2", "job2"),
            C("user3", "job3")
        )

        E(list)
    }
}

Я не мог увидеть полный способ завершить то, что вам делать. Я предполагаю, что вы хотите разрешить будущие классы, которые также реализуют A и B. Единственный способ, который я нашел, будет работать:

interface AB : A, B

class C(
        override var name: String,
        override var job: String
) : AB

class D {
    private fun getList() {
        val list: List<AB> = arrayListOf(
            C("user1", "job1"),
            C("user2", "job2"),
            C("user3", "job3")
        )

        E(list)
        // I want to init E() my constructor here
    }
}

Это очень хорошее решение, даже если оно дает больше интерфейсов. Но обычно это прекрасно:)

1 голос
/ 13 июня 2019

Если я правильно понял ваш вопрос, ваш код нуждается в небольшом улучшении, чтобы решить вашу проблему

interface A {
    var name: String
}

interface B {
    var job: String
}

class C(
    override var name: String,
    override var job: String
) : A, B

class D {
    fun getList(): E<C> = E(
        arrayListOf(
            C("user1", "job1"),
            C("user2", "job2"),
            C("user3", "job3")
        )
    )
}

class E<T>(val list: List<T>) where T : A, T: B {
    fun display() {
        // for (i in 1..10) will throw OutOfBoundsException
        list.forEach {
            println("my name is ${it.name} and I am a ${it.job}")
        }
    }
}

// to test
fun main(args: Array<String>) {
    D().getList().display()

    /* will prints
       my name is user1 and I am a job1
       my name is user2 and I am a job2
       my name is user3 and I am a job3 */
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...