Bug or Feature: Kotlin allows to change 'val' to 'var' in inheritance

后端 未结 2 1844
无人及你
无人及你 2020-12-31 02:35

I just started to explore the language Kotlin. I\'m struggling with inheritance, var&val and side-effects.

If I declare a trait A with a val x

相关标签:
2条回答
  • 2020-12-31 03:20

    I would consider this a feature, as changing val to var imposes weaker usage restrictions and can't break any superclass code. Similar situation can be observed with visibility modifiers:

    trait A {
      protected fun print() {
        ...
      }
    }
    
    class AImpl: A {
      public override fun print() {
        ...
      }
    }
    

    In this example visibility restrictions are also relaxed by a subclass, although some people are considering this technique as an antipattern.

    How do I protect values from being changed by inheritance?

    In kotlin you can explicitly define if any particular class member can be overriden by a subclass using open modifier. In traits, however, all the members are open by default. The solution is to replace trait with class, so you'll be able to control inheritance:

    abstract class A {
      fun print() {
        ...
      }
    
      val x : Int = 2;
    }
    
    class AImpl(x : Int) : A() {
      override var x = x // compilation error
    }
    
    0 讨论(0)
  • 2020-12-31 03:24

    You can make your val final, i.e. forbid overriding it at all. If you define a val in a class, it is final by default.

    Also, if you need to override a val with a var, but do not want the setter to be public, you can say so:

    override var x = 1
        private set
    

    Overriding a val with a var is a feature. It is equivalent to adding a set-method while in the superclass there was only a get-method. And this is rather important in implementing some patterns, such as read-only interfaces.

    There's no way to "protect" your val from being overridden in a way that allows changing mutation other than making it final, because val does not mean "immutable reference", but merely "read-only property". In other words, when your trait A declares a val, it means that through a reference of type A the client can not write this val, no other guarantees intended, or indeed possible.

    P.S. Semicolons are optional in Kotlin, feel free to omit them altogether

    0 讨论(0)
提交回复
热议问题