Search code examples
kotlinkotlin-extension

Setting a kotlin extension


I am unsure if it is possible for a kotlin extension to be set like a java object.

In my program I have a java class called Submission and I wanted to create a kotlin extension of that called categories - an ArrayList - so I made it like this.

var Submission.categories: ArrayList<String>
    get() {
        return this.categories
    }
    set(categories){
        this.categories = categories
    }

However whenever I try set a category the program just crashes with a stackOverflowError like this:

ERR: stack=java.lang.StackOverflowError: stack size 8MB
             at com.....setCategories(Extensions.kt:0)
             at com.....setCategories(Extensions.kt:19)
             at com.....setCategories(Extensions.kt:19)
             at com.....setCategories(Extensions.kt:19)
             at com.....setCategories(Extensions.kt:19)
             at com.....setCategories(Extensions.kt:19)

This seems like the right syntax for declaring kotlin extensions. So I am really unsure of what direction I ought to go about fixing this in. Perhaps I should really just be using plain old inheritance?

Thanks.


Solution

  • Your code throws a StackOverflowError because it calls itself recursively. this.categories just calls the getter it is already in and this.categories = categories calls the setter it is already in.

    Extension properties are only syntactic sugar for a pair of (extension) getters and setters. Inside the property accessors (i.e. the getter and the setter) you can only access what is already publicly accessible from the receiver class. If it has public fields, you can access them, however you can't define new fields. If you want to save additional state but the class has no API for that, you're out of luck.

    What a mutable extension property typically does is redirecting to existing mutating functions. Here's an example.

    //java
    class Foo {
        private List<String> items;
    
        public String myItems() {
            return items;
        }
    }
    
    
    //kotlin
    var Foo.firstItem: String
        get() = myItems()[0]
        set(value) {
            myItems()[0] = value
        }