Доступ к атрибуту объекта в общей функции - PullRequest
0 голосов
/ 21 ноября 2018

Как я могу получить доступ к свойству объекта в универсальной функции?Код, я в настоящее время сделал заявления о error: unresolved reference: name.Как я могу заставить это работать?Ключевое слово where есть, но я не нашел много информации о нем.

fun <T> foo(t:T): String{
    return t.name
}

foo(object {
    val name = "Foo"
})

C ++ эквивалент:

struct {
    int name{10};
}a;

template<typename T>
int foo(T&t) {
    return t.name;
}

foo(a);

Ответы [ 4 ]

0 голосов
/ 21 ноября 2018

Возможно, если вы будете использовать параметры обобщенного типа Kotlin в генериках.

foo(object {
    val name = "Foo"
})


inline fun <reified T> foo(t: T): String =
    T::class.declaredMembers.find { it.name == "name" }!!
    .call(t) as String

Второй вариант - получить ::class непосредственно из t

fun <T: Any> foo(t: T): String =
    t::class.declaredMembers.find { it.name == "name" }!!.call(t) as String

Третий вариант - предоставить для вас верхний предел для общего параметра:

foo( NameProvider {
    val name = "Foo"
})

interface NameProvider {
    val name: String
}

fun <T: NameProvider> foo(t: T): String = t.name
0 голосов
/ 21 ноября 2018

Вы не можете.T может быть экземпляром любого типа во время выполнения.Таким образом, вы не можете получить доступ к свойству.

Вы можете сделать что-то вроде этого, хотя

fun <T : SomeType> foo(t: T): String {
    return t.name
}

open class SomeType(val name: String)

foo(SomeType("value"))

РЕДАКТИРОВАТЬ: Если вы действительно хотите добиться этого с помощью non-named objectтогда я могу думать о чем-то вроде этого.

fun <T : BaseType> foo(t: T): String {
    return t.name
}

interface BaseType {
   val name: String
}

foo(object :BaseType {
        override val name = "value"
})
0 голосов
/ 21 ноября 2018

Вот пример того, как вы можете сделать это в Kotlin, используя рефлексию (примечание: вам даже не нужна эта информация общего типа при использовании этой функции):

fun foo(t : Any) = with(t::class.java.getDeclaredField("name")) {
  isAccessible = true
  get(t) as String
}

with на самом деле не требуется.Конечно, вы можете сделать это совершенно по-другому.Просто хотел показать, как это может выглядеть в Kotlin.

Я сказал что-то типа reified в комментариях, но вам это на самом деле здесь не нужно.

Самая большая проблемаЧтобы решить вашу проблему, у вас есть анонимный тип, который в основном сужает возможные решения просто «использовать отражение»; -)

Если бы у вас был тип / интерфейс следующим образом:

interface Nameable {
  val name : String
}

тогда вы можете изменить свой foo метод на:

fun foo(t : Nameable) = t.name

и вызов его приведет к:

foo(object : Nameable {
  override val name = "Foo"
}

Но, тем не менее, это не C ++ -шаблон, и вам придется создавать множество соответствующих интерфейсов, если вы хотите быть полностью динамическими, и вам придется использовать их при создании анонимных типов и т. д. pp.

0 голосов
/ 21 ноября 2018

Если вы хотите получить доступ к членам определенного типа, тогда вы должны применить верхнюю границу к параметру типа .Можно реализовать так:

fun <T : MyTypeThatHasNameProperty> foo(t: T): String{
    return t.name
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...