temperlang / temper

2 stars 0 forks source link

Private members of interfaces #51

Open tjpalmer opened 8 months ago

tjpalmer commented 8 months ago

Are private members supposed to be allowed in interfaces? If so, we should make them work. If not, we should provide clear error messages.

Examples of current unclear behavior:

$ interface A {
    private b: Int = 1;
    public c(): Int { b }
  }
3: public c(): Int { b }
                     ⇧
[interactive#0:3+20-21]@G: Wrong number of arguments.  Expected 2
interactive#0: A__0
$ interface A {
    private b(): Int { 1 }
    public c(): Int { b() }
  }
interactive#1: A__0
$ class D extends A {
    public d(): Int { b() }
    public e(): Int { c() }
  }
2: public d(): Int { b() }
                     ┗━┛
[interactive#2:2+20-23]@G: Expected subtype of Int, but got Invalid
2: public d(): Int { b() }
                     ⇧
[interactive#2:2+20-21]@G: Expected function type, but got Invalid
2: public d(): Int { b() }
                     ⇧
[interactive#2:2+20-21]@G: No declaration for b
interactive#2: D__0
$ class D extends A {
    public e(): Int { c() }
  }
interactive#3: D__0
$ new D().e()
interactive#4: fail
$ interface A { public c(): Int { 1 } }
interactive#5: A__0
$ class D extends A { public e(): Int { c() } }
interactive#6: D__0
$ new D().e()
interactive#7: 1
ben-509 commented 8 months ago

Prior art notes: Java allows private methods in interfaces to factor code out of default methods. C# allows them, and protected methods. I don’t think Rust has them, but you chatgpt thinks you can hide the details using a private module,

I would not be against disallowing them entirely as complicated default methods seem like a code smell to me, and some backend implementations may be less than ideal. It wouldn't break anything if we change our minds in the future.

mikesamuel commented 8 months ago

My inclination is private members are useful, but probably need to be turned into non-members on most backends.

mikesamuel commented 8 months ago

Because private members are not overridable, and need not be visible outside the scope of the class body, you can pull them out into non-exported top level functions and then any privileged access they perform can be done via the equivalent of JVM access$123 methods.