1
votes

the documentation is really cryptic to me

Usually, the cast operator throws an exception if the cast is not possible. >Thus, we call it unsafe. The unsafe cast in Kotlin is done by the infix operator >as (see operator precedence):

val x: String = y as String

because the word "as" is not easy to find in the internet engines, I cannot understand the use of as and in which way is related to the operator is

Given this code:

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, item: ViewType) {
        holder as NewsViewHolder//why is not called holder2 considering is adressed to NewsViewHolder?
        holder.bind(item as RedditNewsItem)
    }

if I get rid of NewsViewHolder, intelliJ points bind in red. The reason is because there is into the same class an inner class with the method bind

  inner class NewsViewHolder(parent: ViewGroup) : RecyclerView.ViewHolder(
            parent.inflate(R.layout.news_item)) {

        private val imgThumbnail = itemView.img_thumbnail
        private val description = itemView.description
        private val author = itemView.author
        private val comments = itemView.comments
        private val time = itemView.time

        fun bind(item: RedditNewsItem) {
            imgThumbnail.loadImg(item.thumbnail)
            description.text = item.title
            author.text = item.author
            comments.text = "${item.numComments} comments"
            time.text = item.created.getFriendlyTime()

            super.itemView.setOnClickListener { viewActions.onItemSelected(item.url)}
        }
    }

but I pointed in the comments, if the method pass holder with the class Recycler.ViewHolder why the variable holder should be pointed to a method of an inner class, this is really confusing to me. I would rather have done val holderOther =NewsViewHolder.bind(item)

1
Search for type casting.nhaarman
mmh type casting stays also for type conversion, I thought that the casting quoted in the manual was referring to the Cast in Java, i start to understand betterDrocchio

1 Answers

3
votes

The reason why removing the line holder as NewsViewHolder affects the line below is smart casting.

Whenever your code checks a type or performs an as-cast, the Kotlin compiler analyzes the control flow and if the variable cannot change later in time, the compiler allows you to use the variable from that point on as if its type is the one you checked for.

In your example, holder as NewsViewHolder checks the function parameter for being a NewsViewHolder. Given that (1) a function parameter cannot be reassigned and (2) the function will continue execution only if holder is actually a NewsViewHolder (and will throw an exception otherwise), the compiler treats holder as NewsViewHolder in the remainder of the function.

This, in turn, allows you to call the fun bind(item: RedditNewsItem) on the holder without another explicit cast or using a separate variable.

The smart casts respect both as-casts and is-checks. You could instead write it like (though changing the semantics of the original code):

if (holder is NewsViewHolder) {
    holder.bind(item as RedditNewsItem)
} 

Again, the code inside the if clause will run only if holder is NewsViewHolder, so you're allowed to use holder as a NewsViewHolder inside that scope, and, in particular, to call the functions of this type.