Trying some tests with interface inheritance showed some strange and unusual things. But maybe vim9script doesn't support interface inheritance, and an interface attempting to inherit another interface should be flagged as an error.
Flagging it as an error might also be a way to defer handling the issues until spec/implementation is ready, possibly post 9.1.
There are some obvious issues
interface inheritance syntax
Currently the following is supported, Java use extends;
extends seems to better express the intent.
vim9script
interface I1
endinterface
interface I2 implements I1
endinterface
body of an interface inheriting an interface
An interface that inherits an interface is required to repeat the elements
of the parent interface. That may be an accident of using implements.
vim9script
interface I1
def F1(): number
endinterface
interface I2 implements I1
#def F1(): number # <<<<< unexpected requirement
def F2(): number
endinterface
class implementing multiple interfaces
Following gets E1349: Function "F1" of interface "I2" not implemented
when processing class B.
vim9script
interface I1
def F1()
endinterface
interface I2
def F1()
def F2()
endinterface
class A implements I1
def F1()
echo "F1() in 'A'"
enddef
endclass
class B extends A implements I2
# The compiler requires that F1 be implemented here.
# Just invoke super to get expected semantics
#def F1()
# super.F1()
#enddef
def F2()
echo "F2() in 'B'"
enddef
endclass
Using an object member instead of an object method gets the same error,
but the workaround fails with E1369: Duplicate member
vim9script
interface I1
this.val1: number
endinterface
interface I2
this.val1: number
this.val2: number
endinterface
class A implements I1
this.val1: number
endclass
class B extends A implements I2
this.val1: number # can't with it, can't without it
this.val2: number
endclass
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
I am going to make the following changes to the interface specification:
Let me know if you see any issues with this interface specification.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
An interface cannot have abstract methods.
This one got a double take from me; they're all abstract aren't they? Checked it out and saw the errors; a good laugh.
I don't see any potential problems with the spec. Can't wait to try and break it.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
See #13100 which closes this discussion when integrated
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
Closed as of patch 9.0.1906 92d9ee5
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
Closed #13085 as resolved.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
Sorry, this is moving a bit fast for me to keep up.
- An interface can have only read-only and read-write instance variables.
Interfaces generally specify behaviour, not data, and languages with this sort of type system usually allow properties but not fields to appear in interfaces.
Irrespective of whether this is a good idea or not it's surprising that it passes through without comment. Is anyone paying attention?
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
The comment #13085 (comment) summarizes the disposition of interface spec, not just for inheritance. The discussion of what an interface should be has been going on for weeks. There was discussion about this in #12987 (closed with "Seems to be resolved", guess that was only true in a particular context); this was specifically about interface members and properties versus fields. And the first paragraph of #13004 references that discussion. A defining thread seems to be #13004 (reply in thread).
#13041 (comment) reported that there was a general consensus and no more open spec/syntax issues 4 days ago.
With the vim9spec as a starting point, it says
A class can declare its interface, the object members and methods, with a
named interface. This avoids the need for separately specifying the
interface, which is often done in many languages, especially Java.
Which clearly indicates that members are part of an interface.
—
Reply to this email directly, view it on GitHub,.
You are receiving this because you are subscribed to this thread.![]()
Sorry, this is moving a bit fast for me to keep up.
- An interface can have only read-only and read-write instance variables.
Interfaces generally specify behaviour, not data, and languages with this sort of type system usually allow properties but not fields to appear in interfaces.
Irrespective of whether this is a good idea or not it's surprising that it passes through without comment. Is anyone paying attention?
—
Reply to this email directly, view it on GitHub,.
You are receiving this because you are subscribed to this thread.![]()
Is anyone paying attention?
This was not a snarky comment and should, more precisely, have read, "Is anyone else paying attention?". I find it odd that there's apparently no interest in these significant language extensions from the silent majority, even from the usual suspects. The chances of them being in quiet agreement seems unlikely as there are changes being implemented and, well, they're programmers. ;)
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.![]()
As Bram described in https://groups.google.com/g/vim_dev/c/yYpFNUHdRho/m/UTFWOY5VAgAJ (which you quoted in another discussion), it is useful to directly specify an interface from a class definition. If we support this, then interfaces will have both data and behavior
This reasoning is circular. A 'standard' definition of interfaces would only see the public methods exported as part of the "specified" interface. Whether it's declared or specified is immaterial.
class Foo specifies IFoo # static members # member fields def Meth1() echomsg "Implementers must implement me" enddef enddef class Bar implements IFoo def Meth1() echomsg "IFoo is now implemented." enddef endclass
I'll try and work through some toy examples in the next few days but it would be better if we could convince tens of people to also do so.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.![]()
Reopened #13085.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.![]()
Reopening in case it's of use for @dkearns explorations.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.![]()
I had a quick look at the current state of play and it appears disjointed to me.
It's reasonably clear that fields aren't intended to be polymorphic members of the class interface. :help extends says
Object members from the base class are all taken over by the child class. It is not possible to override them (unlike some other languages).
This is unsurprising and the status quo for languages supporting 'classical' OOP.
interfaces being able to declare fields implies that classes should also be able to declare abstract fields and then that these must be overridable.
Public fields are questionable anyway and redefining established PL concepts to give them such special treatment seems like a bad idea for what is, as I understand it, aiming to be a relatively simple and uncontroversial language.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.![]()
If we allow only public read-only variables and not allow read-write variables in an interface, will that help simplify this?
As mentioned by Ernie, read-only variables are part of the interface exposed by a class. Without the read-only variables,
the interface needs to add a getter function for each of the corresponding variable. The read-only variable provide
an optimized way to access the state without the overhead of calling a getter function.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.![]()
interfaces being able to declare fields implies that classes should also be
able to declare abstract fields and then that these must be overridable.
I don't understand this; it's too theoretical for my easy understanding.
As you noted, It is not possible to override them.
relatively simple and uncontroversial language
IMO, the key concept here is "property", I think most agree it should be
in an interface. How can that best be expressed in vim9class?
I find this simple
vim9script
interface I
this.val: number
endinterface
abstract class B implements I
this.val: number
endclass
class C extends B
static _count = 3
def new()
this.val = _count
_count += 2
enddef
endclass
def F(i: I)
echo i.val
enddef
var o1 = C.new()
var o2 = C.new()
F(o1)
F(o2)
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.![]()
IMO, the key concept here is "property", I think most agree it should be in an interface. How can that best be expressed in vim9class?
The reasonable solution is to explicitly implement (capital P) properties but that has been ruled out in the past.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.![]()
solution is to explicitly implement (capital P) properties
Fun article. A problem is vim9script doesn't have a fancy compiler/optimizer and functions are slow (slower than a lambda). Since there are typically more reads than writes, allowing syntax to directly read a property (since the compiler won't optimize a get()) is a clear performance win; the programmer can chose to use get() if needed or for style.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.![]()
As you noted,
It is not possible to override them.
They are being overridden (implemented if you prefer), that's why your example works and the field value can be accessed via the interface reference.
The compiler already appears to be implementing properties under the hood. It's only doing so for the default implementation of simple access to a same-named backing field and it's only doing so for use with interfaces.
Fun article. A problem is vim9script doesn't have a fancy compiler/optimizer and functions are slow (slower than a lambda). Since there are typically more reads than writes, allowing syntax to directly read a property (since the compiler won't optimize a get()) is a clear performance win; the programmer can chose to use get() if needed or for style.
It doesn't need to do anything fancy, it's already doing it. It just needs to recognise the default implementation property syntax and keep on keeping on.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.![]()
It just needs to recognise the default implementation property syntax and keep on keeping on
Are you recommending a syntax change/addition? If so, what?
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.![]()
Closing (again). Thinks it's worked out.
—
Reply to this email directly, view it on GitHub,.
You are receiving this because you commented.![]()
Closed #13085 as resolved.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.![]()