Hi there, if I have the following code: ``` ...
# announcements
r
Hi there, if I have the following code:
Copy code
val f: (Context) -> View = ::TextView
        val text = f(activity)
how do I check that
text
is an 'instance' of
f
?
a
What do you mean with instance of f?
r
Like how to find a relationship between
f
and
text
.
a
You need to find out if
text
was returned by
f
?
r
In Python, when you do:
Copy code
f = TextView
text = f(activity)
you can check
text
is an instance of
f
by doing:
Copy code
isinstance(text, f)
v
Copy code
val isString = when (foo) { is String -> true }
a
in kotlin you can do
text is TextView
r
Is it possible to extract
TextView
out of
f
?
Cos it's not going to be TextView all the time, it could be other views
a
f
is just an ordinary function that creates an instance of
TextView
, so you cant get the type out of it
r
It sounds like if I want to keep a list of classes to instantiate dynamically, I have to keep both the class and constructor function.
a
you could do something like
Copy code
when(text) {
    is TextView -> ...
    is Button -> ...
    ...
}
why do you need to instantiante different classes dynamically?
v
you can also give
Context -> View
an alias, and use
is
to check it.
1
r
Building nested data structure that represents UI elements
Anyway say I have a list of views:
Copy code
val manyViewClasses = listOf(TextView, SomeView)
And I loop them to instantiate:
Copy code
val manyViews = manyViewClasses.map {cls ->
    cls(activity)
}
It won't work, because I'm missing contsructors
It would work if
manyViewClasses
was:
Copy code
val manyViewClasses = listOf(::TextView, ::SomeView)
And just for example I want to compare
manyViews
and
manyViewClasses
like so:
Copy code
manyViews.zip(manyViewClasses).forEach {(view, cls) ->
    if (view.class == cls) {
        println('match')
    }
}
That can't be done, because
cls
is a function, not a class
So this is my workaround:
Copy code
val manyViewClasses = listOf(::TextView, ::SomeView)

val manyViews = manyViewClasses.map {con ->
    con(activity)
}

val manyViewClasses2 = myChangesTo(manyViewClasses)

manyViews.zip(manyViewClasses2).forEach {(view, con) ->
    val newView = con(activity) // <- workaround
    if (view::class == newView::class) {
        println('match')
    }
}
a
and why do you need to know whether
view
has the same class as
con
?
d
This is dynamic programming
Kotlin is a statically typed language
You should consider making an
interface View
and then implement it with
class TextView : View
and
class OtherView : View
I see no point trying to have a list of classes, doing map and zip operations on them and seeing if the type is in there in a loop.
Moreover, you did not explain what the point is despite multiple requests to do so
So I can't really give you an equivalent of what you're trying to achieve that might be considered more idiomatic
r
Thanks for the suggestion @Dico. What I'm trying to do a simple naive diffing between 2 sets of views. So if I have existing views rendered which looks simply like:
Copy code
listOf(TextView, SomeView)
and I try to render a similar
Copy code
listOf(TextView, SomeView)
on top of it, nothing will be applied because it's considered the same.
But if instead I try to render something slightly different, say:
Copy code
listOf(TextView, ImageView)
My program can see that the 2nd View has changed, and replaces
SomeView
with
ImageView
, while leaving
TextView
as is.
Again this is a simple example, a bit more closer to my actual code to represent a set of views is more like:
Copy code
m(::LinearLayout,
     children(
         m(::TextView, attrs(text("Hello"), color("red"))),
         m(::SomeView)))
Copy code
m(::LinearLayout,
     children(
         m(::TextView, attrs(text("Hello"), color("red"))),
         m(::ImageView, attrs(url("<http://www.site.com/image.gif|www.site.com/image.gif>")))))
a
I'd just create the second View-Tree and compare it with the existing one and see how it works performance wise. Only when creating instances of the different View is very expensive, i'd try to optimize it with Builders that know what kind of View they create
d
Copy code
interface View {
    val type: ViewType
}

enum class ViewType(val ktype: KClass<out View>, val ctor: () -> View) {
    TEXT(TextView::class, ::TextView),
    // more
    ;
}
Something like that would probably be considered a bit more idiomatic for what you described
I would prefer for there to exist a constraint between the 2 properties of the enum for better type safety, but it's 5 am
r
Thanks @Andreas Sinz @Dico. The DSL would be ideal, and the interface/enum could be a good compromise.
I would still be keen to see how to make the extra constraint for better type safety.
I'll see if I can apply your suggestions for my little project https://github.com/robinchew/mvil