Override getters in Kotlin?












0














So I have an abstract class Composition, which has two children: one is a Track, and one is an Album (which is a group of Tracks).



class Composition(val name: String, ...)
class Track(name: String): Composition(name)
class Album(name: String, val tracks: List<Track>): Composition(name)


So far, so good. Now, I have the duration that is added. It is abstract in Composition, so I can override it in the children:



abstract class Composition(...){
abstract fun getDuration(): Int
}


Now, I can add override the method in the Track, which takes it as a parameter:



class Track(..., private val duration: Int): Composition(...){
override fun getDuration() = duration
}


And finally, I make the Album, whose duration is the sum of the Tracks:



class Album(..., val tracks: List<Track>): Composition(...){
override fun getDuration() = tracks.sumBy { it.getDuration() }
}


It works as intended, but I do not understand why I cannot simply use tracks.sumBy { it.duration }, since in Kotlin properties are nothing more than getters and setters (I'm thinking about the getDuration in Composition).



I feel like I'm missing something, because if the same code was written in Java, I would be able to call composition.duration as a property -- so that makes me think that Kotlin allows it from Java code, but not from Kotlin code, which is sad.



An other example:



Let's say I have a class named Artist, who wrote multiple Compositions:



class Artist(
val nom: String,
private val _compositions: MutableList<Composition> = ArrayList()
) {

// HERE (I wrote the extension method List<E>.toImmutableList)
fun getCompositions() : List<Composition> = _compositions.toImmutableList()
}


This is standard in Java (exposing immutable versions of Collections via getters, so they are not modified) ; Kotlin doesn't recognize it though:



val artist = Artist("Mozart")
artist.getCompositions() // Legal
artist.compositions // Illegal


I thought about making this a property, but:
- If I choose the type List<E>, I can override the getter to return the immutable list, but I cannot use regular methods (add...) as the List is immutable
- If I choose the type MutableList<E>, I cannot override the getter to return ImmutableList (which is a subclass of List that I wrote, and is obviously not a subclass of MutableList).



There's a chance I'm doing something ridiculous while there is an easy solution, but right now I cannot find it.



In the end, my question is: Why aren't manually-written getters considered properties when written from Kotlin?



And, if I'm mistaking, What is the expected way of solving both of these patterns?










share|improve this question



























    0














    So I have an abstract class Composition, which has two children: one is a Track, and one is an Album (which is a group of Tracks).



    class Composition(val name: String, ...)
    class Track(name: String): Composition(name)
    class Album(name: String, val tracks: List<Track>): Composition(name)


    So far, so good. Now, I have the duration that is added. It is abstract in Composition, so I can override it in the children:



    abstract class Composition(...){
    abstract fun getDuration(): Int
    }


    Now, I can add override the method in the Track, which takes it as a parameter:



    class Track(..., private val duration: Int): Composition(...){
    override fun getDuration() = duration
    }


    And finally, I make the Album, whose duration is the sum of the Tracks:



    class Album(..., val tracks: List<Track>): Composition(...){
    override fun getDuration() = tracks.sumBy { it.getDuration() }
    }


    It works as intended, but I do not understand why I cannot simply use tracks.sumBy { it.duration }, since in Kotlin properties are nothing more than getters and setters (I'm thinking about the getDuration in Composition).



    I feel like I'm missing something, because if the same code was written in Java, I would be able to call composition.duration as a property -- so that makes me think that Kotlin allows it from Java code, but not from Kotlin code, which is sad.



    An other example:



    Let's say I have a class named Artist, who wrote multiple Compositions:



    class Artist(
    val nom: String,
    private val _compositions: MutableList<Composition> = ArrayList()
    ) {

    // HERE (I wrote the extension method List<E>.toImmutableList)
    fun getCompositions() : List<Composition> = _compositions.toImmutableList()
    }


    This is standard in Java (exposing immutable versions of Collections via getters, so they are not modified) ; Kotlin doesn't recognize it though:



    val artist = Artist("Mozart")
    artist.getCompositions() // Legal
    artist.compositions // Illegal


    I thought about making this a property, but:
    - If I choose the type List<E>, I can override the getter to return the immutable list, but I cannot use regular methods (add...) as the List is immutable
    - If I choose the type MutableList<E>, I cannot override the getter to return ImmutableList (which is a subclass of List that I wrote, and is obviously not a subclass of MutableList).



    There's a chance I'm doing something ridiculous while there is an easy solution, but right now I cannot find it.



    In the end, my question is: Why aren't manually-written getters considered properties when written from Kotlin?



    And, if I'm mistaking, What is the expected way of solving both of these patterns?










    share|improve this question

























      0












      0








      0







      So I have an abstract class Composition, which has two children: one is a Track, and one is an Album (which is a group of Tracks).



      class Composition(val name: String, ...)
      class Track(name: String): Composition(name)
      class Album(name: String, val tracks: List<Track>): Composition(name)


      So far, so good. Now, I have the duration that is added. It is abstract in Composition, so I can override it in the children:



      abstract class Composition(...){
      abstract fun getDuration(): Int
      }


      Now, I can add override the method in the Track, which takes it as a parameter:



      class Track(..., private val duration: Int): Composition(...){
      override fun getDuration() = duration
      }


      And finally, I make the Album, whose duration is the sum of the Tracks:



      class Album(..., val tracks: List<Track>): Composition(...){
      override fun getDuration() = tracks.sumBy { it.getDuration() }
      }


      It works as intended, but I do not understand why I cannot simply use tracks.sumBy { it.duration }, since in Kotlin properties are nothing more than getters and setters (I'm thinking about the getDuration in Composition).



      I feel like I'm missing something, because if the same code was written in Java, I would be able to call composition.duration as a property -- so that makes me think that Kotlin allows it from Java code, but not from Kotlin code, which is sad.



      An other example:



      Let's say I have a class named Artist, who wrote multiple Compositions:



      class Artist(
      val nom: String,
      private val _compositions: MutableList<Composition> = ArrayList()
      ) {

      // HERE (I wrote the extension method List<E>.toImmutableList)
      fun getCompositions() : List<Composition> = _compositions.toImmutableList()
      }


      This is standard in Java (exposing immutable versions of Collections via getters, so they are not modified) ; Kotlin doesn't recognize it though:



      val artist = Artist("Mozart")
      artist.getCompositions() // Legal
      artist.compositions // Illegal


      I thought about making this a property, but:
      - If I choose the type List<E>, I can override the getter to return the immutable list, but I cannot use regular methods (add...) as the List is immutable
      - If I choose the type MutableList<E>, I cannot override the getter to return ImmutableList (which is a subclass of List that I wrote, and is obviously not a subclass of MutableList).



      There's a chance I'm doing something ridiculous while there is an easy solution, but right now I cannot find it.



      In the end, my question is: Why aren't manually-written getters considered properties when written from Kotlin?



      And, if I'm mistaking, What is the expected way of solving both of these patterns?










      share|improve this question













      So I have an abstract class Composition, which has two children: one is a Track, and one is an Album (which is a group of Tracks).



      class Composition(val name: String, ...)
      class Track(name: String): Composition(name)
      class Album(name: String, val tracks: List<Track>): Composition(name)


      So far, so good. Now, I have the duration that is added. It is abstract in Composition, so I can override it in the children:



      abstract class Composition(...){
      abstract fun getDuration(): Int
      }


      Now, I can add override the method in the Track, which takes it as a parameter:



      class Track(..., private val duration: Int): Composition(...){
      override fun getDuration() = duration
      }


      And finally, I make the Album, whose duration is the sum of the Tracks:



      class Album(..., val tracks: List<Track>): Composition(...){
      override fun getDuration() = tracks.sumBy { it.getDuration() }
      }


      It works as intended, but I do not understand why I cannot simply use tracks.sumBy { it.duration }, since in Kotlin properties are nothing more than getters and setters (I'm thinking about the getDuration in Composition).



      I feel like I'm missing something, because if the same code was written in Java, I would be able to call composition.duration as a property -- so that makes me think that Kotlin allows it from Java code, but not from Kotlin code, which is sad.



      An other example:



      Let's say I have a class named Artist, who wrote multiple Compositions:



      class Artist(
      val nom: String,
      private val _compositions: MutableList<Composition> = ArrayList()
      ) {

      // HERE (I wrote the extension method List<E>.toImmutableList)
      fun getCompositions() : List<Composition> = _compositions.toImmutableList()
      }


      This is standard in Java (exposing immutable versions of Collections via getters, so they are not modified) ; Kotlin doesn't recognize it though:



      val artist = Artist("Mozart")
      artist.getCompositions() // Legal
      artist.compositions // Illegal


      I thought about making this a property, but:
      - If I choose the type List<E>, I can override the getter to return the immutable list, but I cannot use regular methods (add...) as the List is immutable
      - If I choose the type MutableList<E>, I cannot override the getter to return ImmutableList (which is a subclass of List that I wrote, and is obviously not a subclass of MutableList).



      There's a chance I'm doing something ridiculous while there is an easy solution, but right now I cannot find it.



      In the end, my question is: Why aren't manually-written getters considered properties when written from Kotlin?



      And, if I'm mistaking, What is the expected way of solving both of these patterns?







      kotlin






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 11 at 18:05









      CLOVIS

      172110




      172110
























          2 Answers
          2






          active

          oldest

          votes


















          3














          If you want to use it as property, you should use Kotlin-way to override getter.

          For example:



          abstract class Composition(...){
          abstract val duration: Int
          }

          // You can use "override" in constructor
          // val - is immutable property that has only getter so you can just
          // remove private modifier to make possible get it.
          class Track(..., override val duration: Int): Composition(...){
          ...
          }

          class Album(..., val tracks: List<Track>): Composition(...) {
          override val duration: Int
          get() = tracks.sumBy { it.duration }
          }


          Also there are may be case when you need mutable property that can be changed only inside of object. For this case you can declare mutable property with private setter:



          class SomeClass(value: Int) {
          var value: Int = value
          private set
          }


          Read more in docs: https://kotlinlang.org/docs/reference/properties.html#getters-and-setters






          share|improve this answer























          • So you can override vals as vars?
            – CLOVIS
            Nov 12 at 13:15










          • Yes you can. But not otherwise.
            – OsipXD
            Nov 12 at 14:14



















          3














          You have to define duration as an abstract property and not as an abtract function (https://kotlinlang.org/docs/reference/properties.html#getters-and-setters):



          abstract class Composition(val name: String) {
          abstract val duration: Int
          }
          class Track(name: String, override val duration: Int): Composition(name)
          class Album(name: String, val tracks: List<Track>): Composition(name) {
          override val duration: Int
          get() = tracks.sumBy { it.duration }
          }


          The getter/setter conversion as properties does only work for Java classes (https://kotlinlang.org/docs/reference/java-interop.html#getters-and-setters).






          share|improve this answer





















            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53251647%2foverride-getters-in-kotlin%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            3














            If you want to use it as property, you should use Kotlin-way to override getter.

            For example:



            abstract class Composition(...){
            abstract val duration: Int
            }

            // You can use "override" in constructor
            // val - is immutable property that has only getter so you can just
            // remove private modifier to make possible get it.
            class Track(..., override val duration: Int): Composition(...){
            ...
            }

            class Album(..., val tracks: List<Track>): Composition(...) {
            override val duration: Int
            get() = tracks.sumBy { it.duration }
            }


            Also there are may be case when you need mutable property that can be changed only inside of object. For this case you can declare mutable property with private setter:



            class SomeClass(value: Int) {
            var value: Int = value
            private set
            }


            Read more in docs: https://kotlinlang.org/docs/reference/properties.html#getters-and-setters






            share|improve this answer























            • So you can override vals as vars?
              – CLOVIS
              Nov 12 at 13:15










            • Yes you can. But not otherwise.
              – OsipXD
              Nov 12 at 14:14
















            3














            If you want to use it as property, you should use Kotlin-way to override getter.

            For example:



            abstract class Composition(...){
            abstract val duration: Int
            }

            // You can use "override" in constructor
            // val - is immutable property that has only getter so you can just
            // remove private modifier to make possible get it.
            class Track(..., override val duration: Int): Composition(...){
            ...
            }

            class Album(..., val tracks: List<Track>): Composition(...) {
            override val duration: Int
            get() = tracks.sumBy { it.duration }
            }


            Also there are may be case when you need mutable property that can be changed only inside of object. For this case you can declare mutable property with private setter:



            class SomeClass(value: Int) {
            var value: Int = value
            private set
            }


            Read more in docs: https://kotlinlang.org/docs/reference/properties.html#getters-and-setters






            share|improve this answer























            • So you can override vals as vars?
              – CLOVIS
              Nov 12 at 13:15










            • Yes you can. But not otherwise.
              – OsipXD
              Nov 12 at 14:14














            3












            3








            3






            If you want to use it as property, you should use Kotlin-way to override getter.

            For example:



            abstract class Composition(...){
            abstract val duration: Int
            }

            // You can use "override" in constructor
            // val - is immutable property that has only getter so you can just
            // remove private modifier to make possible get it.
            class Track(..., override val duration: Int): Composition(...){
            ...
            }

            class Album(..., val tracks: List<Track>): Composition(...) {
            override val duration: Int
            get() = tracks.sumBy { it.duration }
            }


            Also there are may be case when you need mutable property that can be changed only inside of object. For this case you can declare mutable property with private setter:



            class SomeClass(value: Int) {
            var value: Int = value
            private set
            }


            Read more in docs: https://kotlinlang.org/docs/reference/properties.html#getters-and-setters






            share|improve this answer














            If you want to use it as property, you should use Kotlin-way to override getter.

            For example:



            abstract class Composition(...){
            abstract val duration: Int
            }

            // You can use "override" in constructor
            // val - is immutable property that has only getter so you can just
            // remove private modifier to make possible get it.
            class Track(..., override val duration: Int): Composition(...){
            ...
            }

            class Album(..., val tracks: List<Track>): Composition(...) {
            override val duration: Int
            get() = tracks.sumBy { it.duration }
            }


            Also there are may be case when you need mutable property that can be changed only inside of object. For this case you can declare mutable property with private setter:



            class SomeClass(value: Int) {
            var value: Int = value
            private set
            }


            Read more in docs: https://kotlinlang.org/docs/reference/properties.html#getters-and-setters







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 11 at 18:28

























            answered Nov 11 at 18:21









            OsipXD

            748919




            748919












            • So you can override vals as vars?
              – CLOVIS
              Nov 12 at 13:15










            • Yes you can. But not otherwise.
              – OsipXD
              Nov 12 at 14:14


















            • So you can override vals as vars?
              – CLOVIS
              Nov 12 at 13:15










            • Yes you can. But not otherwise.
              – OsipXD
              Nov 12 at 14:14
















            So you can override vals as vars?
            – CLOVIS
            Nov 12 at 13:15




            So you can override vals as vars?
            – CLOVIS
            Nov 12 at 13:15












            Yes you can. But not otherwise.
            – OsipXD
            Nov 12 at 14:14




            Yes you can. But not otherwise.
            – OsipXD
            Nov 12 at 14:14













            3














            You have to define duration as an abstract property and not as an abtract function (https://kotlinlang.org/docs/reference/properties.html#getters-and-setters):



            abstract class Composition(val name: String) {
            abstract val duration: Int
            }
            class Track(name: String, override val duration: Int): Composition(name)
            class Album(name: String, val tracks: List<Track>): Composition(name) {
            override val duration: Int
            get() = tracks.sumBy { it.duration }
            }


            The getter/setter conversion as properties does only work for Java classes (https://kotlinlang.org/docs/reference/java-interop.html#getters-and-setters).






            share|improve this answer


























              3














              You have to define duration as an abstract property and not as an abtract function (https://kotlinlang.org/docs/reference/properties.html#getters-and-setters):



              abstract class Composition(val name: String) {
              abstract val duration: Int
              }
              class Track(name: String, override val duration: Int): Composition(name)
              class Album(name: String, val tracks: List<Track>): Composition(name) {
              override val duration: Int
              get() = tracks.sumBy { it.duration }
              }


              The getter/setter conversion as properties does only work for Java classes (https://kotlinlang.org/docs/reference/java-interop.html#getters-and-setters).






              share|improve this answer
























                3












                3








                3






                You have to define duration as an abstract property and not as an abtract function (https://kotlinlang.org/docs/reference/properties.html#getters-and-setters):



                abstract class Composition(val name: String) {
                abstract val duration: Int
                }
                class Track(name: String, override val duration: Int): Composition(name)
                class Album(name: String, val tracks: List<Track>): Composition(name) {
                override val duration: Int
                get() = tracks.sumBy { it.duration }
                }


                The getter/setter conversion as properties does only work for Java classes (https://kotlinlang.org/docs/reference/java-interop.html#getters-and-setters).






                share|improve this answer












                You have to define duration as an abstract property and not as an abtract function (https://kotlinlang.org/docs/reference/properties.html#getters-and-setters):



                abstract class Composition(val name: String) {
                abstract val duration: Int
                }
                class Track(name: String, override val duration: Int): Composition(name)
                class Album(name: String, val tracks: List<Track>): Composition(name) {
                override val duration: Int
                get() = tracks.sumBy { it.duration }
                }


                The getter/setter conversion as properties does only work for Java classes (https://kotlinlang.org/docs/reference/java-interop.html#getters-and-setters).







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 11 at 18:18









                Rene

                1,54115




                1,54115






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.





                    Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                    Please pay close attention to the following guidance:


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53251647%2foverride-getters-in-kotlin%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Full-time equivalent

                    Bicuculline

                    What is this shape that looks like a rectangle with rounded ends called?