This is kind of an odd edge case, but I’m finding ...
# getting-started
l
This is kind of an odd edge case, but I’m finding no documentation on it. In Kotlin, you have inheritance, and can override properties in child classes. Cool cool. You can also set a private visibility on just the set operation of a property. Cool cool. What happens when you do both? Like, you make a property private-set, then extend the class and redeclare it public-read, protected-set. What happens?
s
Did you try it? I get "Private setters are not allowed for open properties".
🤔 1
l
I haven’t; I was hoping there was documentation somewhere I could review.
s
I agree, it doesn't seem to be documented. Perhaps its just a technical limitation rather than a deliberate design choice. I don't see why it wouldn't be theoretically possible in future. It's much the same principle as just overriding a
val
with a
var
.
l
There’s probably deep implementation reasons involved. (I’m discussing adding similar functionality to PHP, and looking at what other langs do; this is a case that came up as problematic.)
g
There is definition of "overridable" callable declaration in Kotlin Spec: https://kotlinlang.org/spec/inheritance.html#overriding The main point is that it is not private.
👍 1
l
OK, so Kotlin’s answer is “just don’t.” Sounds good, thanks. 🙂
b
Overriding properties basically means overriding getter and setter, right. (Ignoring the backing field) IIRC you cannot override private methods in Java either. So that is consitent I’ld say
k
Copy code
Modifiers

The access specifier for an overriding method can allow more, but not less, access than the overridden method. For example, a protected instance method in the superclass can be made public, but not private, in the subclass.

You will get a compile-time error if you attempt to change an instance method in the superclass to a static method in the subclass, and vice versa.
https://docs.oracle.com/javase/tutorial/java/IandI/override.html
s
Well, Java will let you declare the same private method in both a class and its subclass. It just won't be an override.
This is perfectly legal in Java:
Copy code
class Foo {
  private String foo = "foo";
  public String getFoo() { return foo; }
  private void setFoo(String foo) { this.foo = foo; }
}

class Bar extends Foo {
  private String foo = "foo";
  public String getFoo() { return foo; }
  void setFoo(String foo) { this.foo = foo; }
}
So I still don't see any technical reason why it shouldn't work in Kotlin. It seems like it just isn't currently allowed.
c
Sure, that works in Java, but damn is it confusing. With this setup, in
Bar
,
getFoo()
and
super.getFoo()
may return different values, which I believe is very confusing.
You can already get this kind of footguns in Kotlin with
Copy code
abstract class Foo(
    open var foo: Int,
)

class Bar(
    override var foo: Int,
)
but I'd argue making more of these cases is a bad idea.
l
Inheritance is more trouble than it’s worth in language design…
💯 1
c
Interface inheritance is fine! It's abstract and open classes that are a pain, because they are stateful.
👌 1
👍 1
All the examples in this thread have no ambiguity nor weirdness if you use
abstract val
in the parent class.