blob: c1ebce4af6f16003425df2eef991c0d70a423c05 [file] [log] [blame]
Dominique Pellé17dca3c2023-12-14 20:36:32 +01001*vim9class.txt* For Vim version 9.0. Last change: 2023 Dec 14
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00002
3
4 VIM REFERENCE MANUAL by Bram Moolenaar
5
6
Bram Moolenaarbe4e0162023-02-02 13:59:48 +00007NOTE - This is not finished yet, anything can still change! - NOTE
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00008
9
10Vim9 classes, objects, interfaces, types and enums.
11
121. Overview |Vim9-class-overview|
132. A simple class |Vim9-simple-class|
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200143. Class variables and methods |Vim9-class-member|
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000154. Using an abstract class |Vim9-abstract-class|
165. Using an interface |Vim9-using-interface|
176. More class details |Vim9-class|
187. Type definition |Vim9-type|
198. Enum |Vim9-enum|
Bram Moolenaarc1c365c2022-12-04 20:13:24 +000020
219. Rationale
2210. To be done later
23
24==============================================================================
25
261. Overview *Vim9-class-overview*
27
28The fancy term is "object-oriented programming". You can find lots of study
Bram Moolenaarbe4e0162023-02-02 13:59:48 +000029material on this subject. Here we document what |Vim9| script provides,
30assuming you know the basics already. Added are helpful hints about how to
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +020031use this functionality effectively. Vim9 classes and objects cannot be used
32in legacy Vim scripts and legacy functions.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +000033
34The basic item is an object:
35- An object stores state. It contains one or more variables that can each
36 have a value.
Bram Moolenaarbe4e0162023-02-02 13:59:48 +000037- An object provides functions that use and manipulate its state. These
Bram Moolenaarc1c365c2022-12-04 20:13:24 +000038 functions are invoked "on the object", which is what sets it apart from the
39 traditional separation of data and code that manipulates the data.
40- An object has a well defined interface, with typed member variables and
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -070041 methods.
Bram Moolenaarbe4e0162023-02-02 13:59:48 +000042- Objects are created from a class and all objects have the same interface.
43 This does not change at runtime, it is not dynamic.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +000044
45An object can only be created by a class. A class provides:
46- A new() method, the constructor, which returns an object for the class.
47 This method is invoked on the class name: MyClass.new().
Bram Moolenaarbe4e0162023-02-02 13:59:48 +000048- State shared by all objects of the class: class variables (class members).
Bram Moolenaarc1c365c2022-12-04 20:13:24 +000049- A hierarchy of classes, with super-classes and sub-classes, inheritance.
50
51An interface is used to specify properties of an object:
52- An object can declare several interfaces that it implements.
53- Different objects implementing the same interface can be used the same way.
54
55The class hierarchy allows for single inheritance. Otherwise interfaces are
56to be used where needed.
57
58
59Class modeling ~
60
61You can model classes any way you like. Keep in mind what you are building,
62don't try to model the real world. This can be confusing, especially because
63teachers use real-world objects to explain class relations and you might think
64your model should therefore reflect the real world. It doesn't! The model
65should match your purpose.
66
Bram Moolenaarbe4e0162023-02-02 13:59:48 +000067Keep in mind that composition (an object contains other objects) is often
68better than inheritance (an object extends another object). Don't waste time
69trying to find the optimal class model. Or waste time discussing whether a
70square is a rectangle or that a rectangle is a square. It doesn't matter.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +000071
72
73==============================================================================
74
752. A simple class *Vim9-simple-class*
76
Bram Moolenaarbe4e0162023-02-02 13:59:48 +000077Let's start with a simple example: a class that stores a text position (see
78below for how to do this more efficiently): >
Bram Moolenaarc1c365c2022-12-04 20:13:24 +000079
80 class TextPosition
Doug Kearns74da0ee2023-12-14 20:26:26 +010081 var lnum: number
82 var col: number
Bram Moolenaarc1c365c2022-12-04 20:13:24 +000083
84 def new(lnum: number, col: number)
85 this.lnum = lnum
86 this.col = col
87 enddef
88
89 def SetLnum(lnum: number)
90 this.lnum = lnum
91 enddef
92
93 def SetCol(col: number)
94 this.col = col
95 enddef
96
97 def SetPosition(lnum: number, col: number)
98 this.lnum = lnum
99 this.col = col
100 enddef
101 endclass
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000102< *object* *Object*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000103You can create an object from this class with the new() method: >
104
105 var pos = TextPosition.new(1, 1)
errael1d4fcfe2023-12-21 08:34:15 -0800106<
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700107The object variables "lnum" and "col" can be accessed directly: >
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000108
109 echo $'The text position is ({pos.lnum}, {pos.col})'
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000110< *E1317* *E1327*
errael1d4fcfe2023-12-21 08:34:15 -0800111If you have been using other object-oriented languages you will notice that in
112Vim, within a class definition, the object members are consistently referred
113to with the "this." prefix. This is different from languages like Java and
114TypeScript. The naming convention makes the object members easy to spot.
115Also, when a variable does not have the "this." prefix you know it is not an
116object variable.
117 *E1411*
118From outside the class definition, access an object's methods and variables by
119using the object name followed by a dot following by the member: >
120
121 pos.lnum
122 pos.setCol(10)
123<
124 *E1405* *E1406*
125A class name cannot be used as an expression. A class name cannot be used in
126the left-hand-side of an assignment.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000127
128
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700129Object variable write access ~
Ernie Rael03042a22023-11-11 08:53:32 +0100130 *read-only-variable*
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700131Now try to change an object variable directly: >
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000132
133 pos.lnum = 9
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000134< *E1335*
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700135This will give you an error! That is because by default object variables can
136be read but not set. That's why the TextPosition class provides a method for
137it: >
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000138
139 pos.SetLnum(9)
140
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700141Allowing to read but not set an object variable is the most common and safest
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000142way. Most often there is no problem using a value, while setting a value may
143have side effects that need to be taken care of. In this case, the SetLnum()
144method could check if the line number is valid and either give an error or use
145the closest valid value.
Ernie Rael03042a22023-11-11 08:53:32 +0100146 *:public* *public-variable* *E1331*
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700147If you don't care about side effects and want to allow the object variable to
148be changed at any time, you can make it public: >
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000149
150 public this.lnum: number
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000151 public this.col: number
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000152
153Now you don't need the SetLnum(), SetCol() and SetPosition() methods, setting
154"pos.lnum" directly above will no longer give an error.
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200155 *E1326*
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700156If you try to set an object variable that doesn't exist you get an error: >
Bram Moolenaarf1dcd142022-12-31 15:30:45 +0000157 pos.other = 9
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200158< E1326: Member not found on object "TextPosition": other ~
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000159
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200160 *E1376*
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700161A object variable cannot be accessed using the class name.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000162
Ernie Rael03042a22023-11-11 08:53:32 +0100163Protected variables ~
164 *protected-variable* *E1332* *E1333*
165On the other hand, if you do not want the object variables to be read directly
166from outside the class or its sub-classes, you can make them protected. This
167is done by prefixing an underscore to the name: >
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000168
Doug Kearns74da0ee2023-12-14 20:26:26 +0100169 var _lnum: number
170 var _col number
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000171
Ernie Rael03042a22023-11-11 08:53:32 +0100172Now you need to provide methods to get the value of the protected variables.
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000173These are commonly called getters. We recommend using a name that starts with
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000174"Get": >
175
176 def GetLnum(): number
177 return this._lnum
178 enddef
179
180 def GetCol() number
181 return this._col
182 enddef
183
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700184This example isn't very useful, the variables might as well have been public.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000185It does become useful if you check the value. For example, restrict the line
186number to the total number of lines: >
187
188 def GetLnum(): number
189 if this._lnum > this._lineCount
190 return this._lineCount
191 endif
192 return this._lnum
193 enddef
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200194<
Ernie Rael03042a22023-11-11 08:53:32 +0100195Protected methods ~
196 *protected-method* *E1366*
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +0200197If you want object methods to be accessible only from other methods of the
198same class and not used from outside the class, then you can make them
Ernie Rael03042a22023-11-11 08:53:32 +0100199protected. This is done by prefixing the method name with an underscore: >
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +0200200
201 class SomeClass
202 def _Foo(): number
203 return 10
204 enddef
205 def Bar(): number
206 return this._Foo()
207 enddef
208 endclass
209<
Ernie Rael03042a22023-11-11 08:53:32 +0100210Accessing a protected method outside the class will result in an error (using
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +0200211the above class): >
212
213 var a = SomeClass.new()
214 a._Foo()
215<
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000216Simplifying the new() method ~
Yegappan Lakshmanan413f8392023-09-28 22:46:37 +0200217 *new()* *constructor*
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700218Many constructors take values for the object variables. Thus you very often
219see this pattern: >
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000220
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000221 class SomeClass
Doug Kearns74da0ee2023-12-14 20:26:26 +0100222 var lnum: number
223 var col: number
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000224
225 def new(lnum: number, col: number)
226 this.lnum = lnum
227 this.col = col
228 enddef
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000229 endclass
h-eastdb385522023-09-28 22:18:19 +0200230<
231 *E1390*
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700232Not only is this text you need to write, it also has the type of each
Dominique Pellé17dca3c2023-12-14 20:36:32 +0100233variable twice. Since this is so common a shorter way to write new() is
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700234provided: >
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000235
236 def new(this.lnum, this.col)
237 enddef
238
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700239The semantics are easy to understand: Providing the object variable name,
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000240including "this.", as the argument to new() means the value provided in the
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700241new() call is assigned to that object variable. This mechanism comes from the
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000242Dart language.
243
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700244Putting together this way of using new() and making the variables public
245results in a much shorter class definition than what we started with: >
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000246
247 class TextPosition
Doug Kearns74da0ee2023-12-14 20:26:26 +0100248 public var lnum: number
249 public var col: number
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000250
251 def new(this.lnum, this.col)
252 enddef
253
254 def SetPosition(lnum: number, col: number)
255 this.lnum = lnum
256 this.col = col
257 enddef
258 endclass
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000259
260The sequence of constructing a new object is:
2611. Memory is allocated and cleared. All values are zero/false/empty.
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07002622. For each declared object variable that has an initializer, the expression
263 is evaluated and assigned to the variable. This happens in the sequence
264 the variables are declared in the class.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00002653. Arguments in the new() method in the "this.name" form are assigned.
2664. The body of the new() method is executed.
267
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000268If the class extends a parent class, the same thing happens. In the second
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700269step the object variables of the parent class are initialized first. There is
270no need to call "super()" or "new()" on the parent.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000271
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200272 *E1365*
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +0200273When defining the new() method the return type should not be specified. It
274always returns an object of the class.
275
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200276 *E1386*
277When invoking an object method, the method name should be preceded by the
Dominique Pellé17dca3c2023-12-14 20:36:32 +0100278object variable name. An object method cannot be invoked using the class
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200279name.
280
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000281==============================================================================
282
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02002833. Class Variables and Methods *Vim9-class-member*
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000284
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200285 *:static* *E1337* *E1338* *E1368*
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000286Class members are declared with "static". They are used by the name without a
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200287prefix in the class where they are defined: >
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000288
289 class OtherThing
Doug Kearns74da0ee2023-12-14 20:26:26 +0100290 var size: number
291 static var totalSize: number
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000292
293 def new(this.size)
294 totalSize += this.size
295 enddef
296 endclass
297< *E1340* *E1341*
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700298Since the name is used as-is, shadowing the name by a method argument name
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000299or local variable name is not allowed.
300
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200301 *E1374* *E1375* *E1384* *E1385*
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200302To access a class member outside of the class where it is defined, the class
303name prefix must be used. A class member cannot be accessed using an object.
304
Ernie Rael03042a22023-11-11 08:53:32 +0100305Just like object members the access can be made protected by using an
306underscore as the first character in the name, and it can be made public by
307prefixing "public": >
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000308
309 class OtherThing
Doug Kearns74da0ee2023-12-14 20:26:26 +0100310 static var total: number # anybody can read, only class can write
311 static var _sum: number # only class can read and write
312 public static var result: number # anybody can read and write
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000313 endclass
314<
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200315 *class-method*
316Class methods are also declared with "static". They can use the class
317variables but they have no access to the object variables, they cannot use the
h_eastba77bbb2023-10-03 04:47:13 +0900318"this" keyword:
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200319>
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000320 class OtherThing
Doug Kearns74da0ee2023-12-14 20:26:26 +0100321 var size: number
322 static var totalSize: number
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000323
324 # Clear the total size and return the value it had before.
325 static def ClearTotalSize(): number
326 var prev = totalSize
327 totalSize = 0
328 return prev
329 enddef
330 endclass
331
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200332Inside the class the class method can be called by name directly, outside the
333class the class name must be prefixed: `OtherThing.ClearTotalSize()`. To use
334a super class method in a child class, the class name must be prefixed.
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000335
Ernie Rael03042a22023-11-11 08:53:32 +0100336Just like object methods the access can be made protected by using an
337underscore as the first character in the method name: >
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +0200338
339 class OtherThing
340 static def _Foo()
341 echo "Foo"
342 enddef
343 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200344 _Foo()
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +0200345 enddef
346 endclass
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +0200347<
348 *E1370*
349Note that constructors cannot be declared as "static", because they always
350are.
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +0200351
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200352To access the class methods and class variables of a super class in an
353extended class, the class name prefix should be used just as from anywhere
354outside of the defining class: >
355
356 vim9script
357 class Vehicle
Doug Kearns74da0ee2023-12-14 20:26:26 +0100358 static var nextID: number = 1000
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200359 static def GetID(): number
360 nextID += 1
361 return nextID
362 enddef
363 endclass
364 class Car extends Vehicle
Doug Kearns74da0ee2023-12-14 20:26:26 +0100365 var myID: number
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200366 def new()
367 this.myID = Vehicle.GetID()
368 enddef
369 endclass
370<
371Class variables and methods are not inherited by a child class. A child class
372can declare a static variable or a method with the same name as the one in the
373super class. Depending on the class where the member is used the
374corresponding class member will be used. The type of the class member in a
375child class can be different from that in the super class.
376
Yegappan Lakshmananff6f0d52023-12-21 16:46:18 +0100377The double underscore (__) prefix for a class or object method name is
378reserved for future use.
379
Yegappan Lakshmanane5437c52023-12-16 14:11:19 +0100380 *object-final-variable* *E1409*
381The |:final| keyword can be used to make a class or object variable a
382constant. Examples: >
383
384 class A
385 final v1 = [1, 2] # final object variable
386 public final v2 = {x: 1} # final object variable
387 static final v3 = 'abc' # final class variable
388 public static final v4 = 0z10 # final class variable
389 endclass
390<
391A final variable can be changed only from a constructor function. Example: >
392
393 class A
394 final v1: list<number>
395 def new()
396 this.v1 = [1, 2]
397 enddef
398 endclass
399 var a = A.new()
400 echo a.v1
401<
402Note that the value of a final variable can be changed. Example: >
403
404 class A
405 public final v1 = [1, 2]
406 endclass
407 var a = A.new()
408 a.v1[0] = 6 # OK
409 a.v1->add(3) # OK
410 a.v1 = [3, 4] # Error
411<
412 *E1408*
413Final variables are not supported in an interface. A class or object method
414cannot be final.
415
416 *object-const-variable*
417The |:const| keyword can be used to make a class or object variable and the
418value a constant. Examples: >
419
420 class A
421 const v1 = [1, 2] # const object variable
422 public const v2 = {x: 1} # const object variable
423 static const v3 = 'abc' # const class variable
424 public static const v4 = 0z10 # const class variable
425 endclass
426<
427A const variable can be changed only from a constructor function. Example: >
428
429 class A
430 const v1: list<number>
431 def new()
432 this.v1 = [1, 2]
433 enddef
434 endclass
435 var a = A.new()
436 echo a.v1
437<
438A const variable and its value cannot be changed. Example: >
439
440 class A
441 public const v1 = [1, 2]
442 endclass
443 var a = A.new()
444 a.v1[0] = 6 # Error
445 a.v1->add(3) # Error
446 a.v1 = [3, 4] # Error
447<
448 *E1410*
449Const variables are not supported in an interface. A class or object method
450cannot be a const.
451
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000452==============================================================================
453
4544. Using an abstract class *Vim9-abstract-class*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000455
456An abstract class forms the base for at least one sub-class. In the class
457model one often finds that a few classes have the same properties that can be
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000458shared, but a class with these properties does not have enough state to create
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000459an object from. A sub-class must extend the abstract class and add the
460missing state and/or methods before it can be used to create objects for.
461
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000462For example, a Shape class could store a color and thickness. You cannot
463create a Shape object, it is missing the information about what kind of shape
464it is. The Shape class functions as the base for a Square and a Triangle
465class, for which objects can be created. Example: >
466
467 abstract class Shape
Doug Kearns74da0ee2023-12-14 20:26:26 +0100468 var color = Color.Black
469 var thickness = 10
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000470 endclass
471
472 class Square extends Shape
Doug Kearns74da0ee2023-12-14 20:26:26 +0100473 var size: number
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000474
475 def new(this.size)
476 enddef
477 endclass
478
479 class Triangle extends Shape
Doug Kearns74da0ee2023-12-14 20:26:26 +0100480 var base: number
481 var height: number
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000482
483 def new(this.base, this.height)
484 enddef
485 endclass
486<
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000487An abstract class is defined the same way as a normal class, except that it
488does not have any new() method. *E1359*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000489
h_east596a9f22023-11-21 21:24:23 +0900490 *abstract-method* *E1371* *E1372*
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +0200491An abstract method can be defined in an abstract class by using the "abstract"
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700492prefix when defining the method: >
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +0200493
494 abstract class Shape
495 abstract def Draw()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200496 abstract static def SetColor()
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +0200497 endclass
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200498<
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +0100499A static method in an abstract class cannot be an abstract method.
500
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200501 *E1373*
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +0200502A class extending the abstract class must implement all the abstract methods.
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200503The signature (arguments, argument types and return type) must be exactly the
Yegappan Lakshmanan26e8f7b2023-10-06 10:24:10 -0700504same. If the return type of a method is a class, then that class or one of
505its subclasses can be used in the extended method. Class methods in an
506abstract class can also be abstract methods.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000507
508==============================================================================
509
Bram Moolenaarbe4e0162023-02-02 13:59:48 +00005105. Using an interface *Vim9-using-interface*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000511
512The example above with Shape, Square and Triangle can be made more useful if
513we add a method to compute the surface of the object. For that we create the
514interface called HasSurface, which specifies one method Surface() that returns
515a number. This example extends the one above: >
516
517 abstract class Shape
Doug Kearns74da0ee2023-12-14 20:26:26 +0100518 var color = Color.Black
519 var thickness = 10
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000520 endclass
521
522 interface HasSurface
523 def Surface(): number
524 endinterface
525
526 class Square extends Shape implements HasSurface
Doug Kearns74da0ee2023-12-14 20:26:26 +0100527 var size: number
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000528
529 def new(this.size)
530 enddef
531
532 def Surface(): number
533 return this.size * this.size
534 enddef
535 endclass
536
537 class Triangle extends Shape implements HasSurface
Doug Kearns74da0ee2023-12-14 20:26:26 +0100538 var base: number
539 var height: number
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000540
541 def new(this.base, this.height)
542 enddef
543
544 def Surface(): number
545 return this.base * this.height / 2
546 enddef
547 endclass
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200548<
549 *E1348* *E1349* *E1367* *E1382* *E1383*
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000550If a class declares to implement an interface, all the items specified in the
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200551interface must appear in the class, with the same types.
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000552
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000553The interface name can be used as a type: >
554
555 var shapes: list<HasSurface> = [
556 Square.new(12),
557 Triangle.new(8, 15),
558 ]
559 for shape in shapes
560 echo $'the surface is {shape.Surface()}'
561 endfor
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200562<
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200563 *E1378* *E1379* *E1380* *E1387*
564An interface can contain only object methods and read-only object variables.
Ernie Rael03042a22023-11-11 08:53:32 +0100565An interface cannot contain read-write or protected object variables,
566protected object methods, class variables and class methods.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000567
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200568An interface can extend another interface using "extends". The sub-interface
569inherits all the instance variables and methods from the super interface.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000570
571==============================================================================
572
Bram Moolenaarbe4e0162023-02-02 13:59:48 +00005736. More class details *Vim9-class* *Class* *class*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000574
575Defining a class ~
576 *:class* *:endclass* *:abstract*
577A class is defined between `:class` and `:endclass`. The whole class is
578defined in one script file. It is not possible to add to a class later.
579
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000580A class can only be defined in a |Vim9| script file. *E1316*
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000581A class cannot be defined inside a function.
582
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000583It is possible to define more than one class in a script file. Although it
584usually is better to export only one main class. It can be useful to define
585types, enums and helper classes though.
586
587The `:abstract` keyword may be prefixed and `:export` may be used. That gives
588these variants: >
589
590 class ClassName
591 endclass
592
593 export class ClassName
594 endclass
595
596 abstract class ClassName
597 endclass
598
599 export abstract class ClassName
600 endclass
601<
602 *E1314*
603The class name should be CamelCased. It must start with an uppercase letter.
604That avoids clashing with builtin types.
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000605 *E1315*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000606After the class name these optional items can be used. Each can appear only
607once. They can appear in any order, although this order is recommended: >
608 extends ClassName
609 implements InterfaceName, OtherInterface
610 specifies SomeInterface
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200611< *E1355* *E1369*
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700612Each variable and method name can be used only once. It is not possible to
613define a method with the same name and different type of arguments. It is not
Ernie Rael03042a22023-11-11 08:53:32 +0100614possible to use a public and protected member variable with the same name. A
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700615object variable name used in a super class cannot be reused in a child class.
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000616
617
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700618Object Variable Initialization ~
Ernie Rael03042a22023-11-11 08:53:32 +0100619
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700620If the type of a variable is not explicitly specified in a class, then it is
621set to "any" during class definition. When an object is instantiated from the
622class, then the type of the variable is set.
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200623
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +0200624The following reserved keyword names cannot be used as an object or class
625variable name: "super", "this", "true", "false", "null", "null_blob",
626"null_dict", "null_function", "null_list", "null_partial", "null_string",
627"null_channel" and "null_job".
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200628
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000629Extending a class ~
630 *extends*
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000631A class can extend one other class. *E1352* *E1353* *E1354*
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000632The basic idea is to build on top of an existing class, add properties to it.
633
634The extended class is called the "base class" or "super class". The new class
635is called the "child class".
636
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700637Object variables from the base class are all taken over by the child class. It
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000638is not possible to override them (unlike some other languages).
639
640 *E1356* *E1357* *E1358*
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +0200641Object methods of the base class can be overruled. The signature (arguments,
Yegappan Lakshmanan26e8f7b2023-10-06 10:24:10 -0700642argument types and return type) must be exactly the same. If the return type
643of a method is a class, then that class or one of its subclasses can be used
644in the extended method. The method of the base class can be called by
645prefixing "super.".
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000646
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200647 *E1377*
Ernie Rael03042a22023-11-11 08:53:32 +0100648The access level of a method (public or protected) in a child class should be
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200649the same as the super class.
650
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000651Other object methods of the base class are taken over by the child class.
652
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700653Class methods, including methods starting with "new", can be overruled, like
654with object methods. The method on the base class can be called by prefixing
655the name of the class (for class methods) or "super.".
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000656
657Unlike other languages, the constructor of the base class does not need to be
658invoked. In fact, it cannot be invoked. If some initialization from the base
659class also needs to be done in a child class, put it in an object method and
660call that method from every constructor().
661
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700662If the base class did not specify a new() method then one was automatically
663created. This method will not be taken over by the child class. The child
664class can define its own new() method, or, if there isn't one, a new() method
665will be added automatically.
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000666
667
668A class implementing an interface ~
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200669 *implements* *E1346* *E1347* *E1389*
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000670A class can implement one or more interfaces. The "implements" keyword can
671only appear once *E1350* . Multiple interfaces can be specified, separated by
672commas. Each interface name can appear only once. *E1351*
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000673
674
675A class defining an interface ~
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000676 *specifies*
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700677A class can declare its interface, the object variables and methods, with a
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000678named interface. This avoids the need for separately specifying the
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000679interface, which is often done in many languages, especially Java.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000680
681
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000682Items in a class ~
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200683 *E1318* *E1325* *E1388*
Bram Moolenaardd60c362023-02-27 15:49:53 +0000684Inside a class, in between `:class` and `:endclass`, these items can appear:
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700685- An object variable declaration: >
Doug Kearns74da0ee2023-12-14 20:26:26 +0100686 var _protectedVariableName: memberType
687 var readonlyVariableName: memberType
688 public var readwriteVariableName: memberType
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700689- A class variable declaration: >
Doug Kearns74da0ee2023-12-14 20:26:26 +0100690 static var _protectedClassVariableName: memberType
691 static var readonlyClassVariableName: memberType
692 static var public readwriteClassVariableName: memberType
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000693- A constructor method: >
Bram Moolenaar938ae282023-02-20 20:44:55 +0000694 def new(arguments)
695 def newName(arguments)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200696- A class method: >
697 static def SomeMethod(arguments)
Ernie Rael03042a22023-11-11 08:53:32 +0100698 static def _ProtectedMethod(arguments)
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000699- An object method: >
Bram Moolenaar938ae282023-02-20 20:44:55 +0000700 def SomeMethod(arguments)
Ernie Rael03042a22023-11-11 08:53:32 +0100701 def _ProtectedMethod(arguments)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200702
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700703For the object variable the type must be specified. The best way is to do
704this explicitly with ": {type}". For simple types you can also use an
705initializer, such as "= 123", and Vim will see that the type is a number.
706Avoid doing this for more complex types and when the type will be incomplete.
707For example: >
Doug Kearns74da0ee2023-12-14 20:26:26 +0100708 var nameList = []
Bram Moolenaarf1dcd142022-12-31 15:30:45 +0000709This specifies a list, but the item type is unknown. Better use: >
Doug Kearns74da0ee2023-12-14 20:26:26 +0100710 var nameList: list<string>
Bram Moolenaarf1dcd142022-12-31 15:30:45 +0000711The initialization isn't needed, the list is empty by default.
712 *E1330*
713Some types cannot be used, such as "void", "null" and "v:none".
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000714
715
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000716Defining an interface ~
717 *:interface* *:endinterface*
718An interface is defined between `:interface` and `:endinterface`. It may be
719prefixed with `:export`: >
720
721 interface InterfaceName
722 endinterface
723
724 export interface InterfaceName
725 endinterface
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000726< *E1344*
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700727An interface can declare object variables, just like in a class but without
728any initializer.
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000729 *E1345*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000730An interface can declare methods with `:def`, including the arguments and
731return type, but without the body and without `:enddef`. Example: >
732
733 interface HasSurface
Doug Kearns74da0ee2023-12-14 20:26:26 +0100734 var size: number
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000735 def Surface(): number
736 endinterface
737
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000738An interface name must start with an uppercase letter. *E1343*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000739The "Has" prefix can be used to make it easier to guess this is an interface
740name, with a hint about what it provides.
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000741An interface can only be defined in a |Vim9| script file. *E1342*
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200742An interface cannot "implement" another interface but it can "extend" another
743interface. *E1381*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000744
745
Bram Moolenaar938ae282023-02-20 20:44:55 +0000746null object ~
747
Bram Moolenaardd60c362023-02-27 15:49:53 +0000748When a variable is declared to have the type of an object, but it is not
Bram Moolenaar938ae282023-02-20 20:44:55 +0000749initialized, the value is null. When trying to use this null object Vim often
750does not know what class was supposed to be used. Vim then cannot check if
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700751a variable name is correct and you will get an "Using a null object" error,
h_eastba77bbb2023-10-03 04:47:13 +0900752even when the variable name is invalid. *E1360* *E1362*
Bram Moolenaar938ae282023-02-20 20:44:55 +0000753
754
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000755Default constructor ~
Yegappan Lakshmanan413f8392023-09-28 22:46:37 +0200756 *default-constructor*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000757In case you define a class without a new() method, one will be automatically
758defined. This default constructor will have arguments for all the object
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700759variables, in the order they were specified. Thus if your class looks like: >
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000760
761 class AutoNew
Doug Kearns74da0ee2023-12-14 20:26:26 +0100762 var name: string
763 var age: number
764 var gender: Gender
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000765 endclass
766
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700767Then the default constructor will be: >
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000768
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000769 def new(this.name = v:none, this.age = v:none, this.gender = v:none)
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000770 enddef
771
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000772The "= v:none" default values make the arguments optional. Thus you can also
773call `new()` without any arguments. No assignment will happen and the default
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700774value for the object variables will be used. This is a more useful example,
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000775with default values: >
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000776
777 class TextPosition
Doug Kearns74da0ee2023-12-14 20:26:26 +0100778 var lnum: number = 1
779 var col: number = 1
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000780 endclass
781
782If you want the constructor to have mandatory arguments, you need to write it
783yourself. For example, if for the AutoNew class above you insist on getting
784the name, you can define the constructor like this: >
785
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000786 def new(this.name, this.age = v:none, this.gender = v:none)
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000787 enddef
Yegappan Lakshmanan563e6442023-12-05 08:19:06 -0800788<
789When using the default new() method, if the order of the object variables in
790the class is changed later, then all the callers of the default new() method
791needs to change. To avoid this, the new() method can be explicitly defined
792without any arguments.
793
794 *E1328*
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000795Note that you cannot use another default value than "v:none" here. If you
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700796want to initialize the object variables, do it where they are declared. This
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000797way you only need to look in one place for the default values.
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000798
Ernie Rael03042a22023-11-11 08:53:32 +0100799All object variables will be used in the default constructor, including
800protected access ones.
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000801
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700802If the class extends another one, the object variables of that class will come
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000803first.
804
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000805
806Multiple constructors ~
807
808Normally a class has just one new() constructor. In case you find that the
809constructor is often called with the same arguments you may want to simplify
810your code by putting those arguments into a second constructor method. For
811example, if you tend to use the color black a lot: >
812
813 def new(this.garment, this.color, this.size)
814 enddef
815 ...
816 var pants = new(Garment.pants, Color.black, "XL")
817 var shirt = new(Garment.shirt, Color.black, "XL")
818 var shoes = new(Garment.shoes, Color.black, "45")
819
820Instead of repeating the color every time you can add a constructor that
821includes it: >
822
823 def newBlack(this.garment, this.size)
824 this.color = Color.black
825 enddef
826 ...
827 var pants = newBlack(Garment.pants, "XL")
828 var shirt = newBlack(Garment.shirt, "XL")
829 var shoes = newBlack(Garment.shoes, "9.5")
830
831Note that the method name must start with "new". If there is no method called
832"new()" then the default constructor is added, even though there are other
833constructor methods.
834
835
836==============================================================================
837
Bram Moolenaarbe4e0162023-02-02 13:59:48 +00008387. Type definition *Vim9-type* *:type*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000839
Yegappan Lakshmanan2a71b542023-12-14 20:03:03 +0100840 *E1393* *E1395* *E1396* *E1397* *E1398*
841A type definition is giving a name to a type specification. This is also
842known as a "type alias". The type alias can be used wherever a built-in type
843can be used. Example: >
Yegappan Lakshmanan26e8f7b2023-10-06 10:24:10 -0700844
Yegappan Lakshmanan2a71b542023-12-14 20:03:03 +0100845 type ListOfStrings = list<string>
846 var s: ListOfStrings = ['a', 'b']
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000847
Yegappan Lakshmanan2a71b542023-12-14 20:03:03 +0100848 def ProcessStr(str: ListOfStrings): ListOfStrings
849 return str
850 enddef
851 echo ProcessStr(s)
852<
853 *E1394*
854A type alias name must start with an upper case character. Only existing
855types can be aliased.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000856
Yegappan Lakshmanan2a71b542023-12-14 20:03:03 +0100857 *E1399*
858A type alias can be created only at the script level and not inside a
859function. A type alias can be exported and used across scripts.
860
861 *E1400* *E1401* *E1402* *E1403* *E1407*
862A type alias cannot be used as an expression. A type alias cannot be used in
863the left-hand-side of an assignment.
864
865For a type alias name, the |typename()| function returns the type that is
866aliased: >
867
868 type ListOfStudents = list<dict<any>>
869 echo typename(ListOfStudents)
870 typealias<list<dict<any>>>
871<
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000872==============================================================================
873
Bram Moolenaarbe4e0162023-02-02 13:59:48 +00008748. Enum *Vim9-enum* *:enum* *:endenum*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000875
Yegappan Lakshmanan26e8f7b2023-10-06 10:24:10 -0700876{not implemented yet}
877
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000878An enum is a type that can have one of a list of values. Example: >
879
880 :enum Color
881 White
882 Red
883 Green
884 Blue
885 Black
886 :endenum
887
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000888
889==============================================================================
890
8919. Rationale
892
893Most of the choices for |Vim9| classes come from popular and recently
894developed languages, such as Java, TypeScript and Dart. The syntax has been
895made to fit with the way Vim script works, such as using `endclass` instead of
896using curly braces around the whole class.
897
898Some common constructs of object-oriented languages were chosen very long ago
899when this kind of programming was still new, and later found to be
900sub-optimal. By this time those constructs were widely used and changing them
901was not an option. In Vim we do have the freedom to make different choices,
902since classes are completely new. We can make the syntax simpler and more
903consistent than what "old" languages use. Without diverting too much, it
904should still mostly look like what you know from existing languages.
905
906Some recently developed languages add all kinds of fancy features that we
907don't need for Vim. But some have nice ideas that we do want to use.
908Thus we end up with a base of what is common in popular languages, dropping
909what looks like a bad idea, and adding some nice features that are easy to
910understand.
911
912The main rules we use to make decisions:
913- Keep it simple.
914- No surprises, mostly do what other languages are doing.
915- Avoid mistakes from the past.
916- Avoid the need for the script writer to consult the help to understand how
917 things work, most things should be obvious.
918- Keep it consistent.
919- Aim at an average size plugin, not at a huge project.
920
921
922Using new() for the constructor ~
923
924Many languages use the class name for the constructor method. A disadvantage
925is that quite often this is a long name. And when changing the class name all
926constructor methods need to be renamed. Not a big deal, but still a
927disadvantage.
928
929Other languages, such as TypeScript, use a specific name, such as
930"constructor()". That seems better. However, using "new" or "new()" to
931create a new object has no obvious relation with "constructor()".
932
933For |Vim9| script using the same method name for all constructors seemed like
934the right choice, and by calling it new() the relation between the caller and
935the method being called is obvious.
936
937
938No overloading of the constructor ~
939
940In Vim script, both legacy and |Vim9| script, there is no overloading of
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700941methods. That means it is not possible to use the same method name with
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000942different types of arguments. Therefore there also is only one new()
943constructor.
944
945With |Vim9| script it would be possible to support overloading, since
946arguments are typed. However, this gets complicated very quickly. Looking at
947a new() call one has to inspect the types of the arguments to know which of
948several new() methods is actually being called. And that can require
949inspecting quite a bit of code. For example, if one of the arguments is the
950return value of a method, you need to find that method to see what type it is
951returning.
952
953Instead, every constructor has to have a different name, starting with "new".
954That way multiple constructors with different arguments are possible, while it
955is very easy to see which constructor is being used. And the type of
956arguments can be properly checked.
957
958
959No overloading of methods ~
960
961Same reasoning as for the constructor: It is often not obvious what type
962arguments have, which would make it difficult to figure out what method is
963actually being called. Better just give the methods a different name, then
964type checking will make sure it works as you intended. This rules out
965polymorphism, which we don't really need anyway.
966
967
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000968Single inheritance and interfaces ~
969
970Some languages support multiple inheritance. Although that can be useful in
971some cases, it makes the rules of how a class works quite complicated.
972Instead, using interfaces to declare what is supported is much simpler. The
973very popular Java language does it this way, and it should be good enough for
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000974Vim. The "keep it simple" rule applies here.
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000975
976Explicitly declaring that a class supports an interface makes it easy to see
977what a class is intended for. It also makes it possible to do proper type
978checking. When an interface is changed any class that declares to implement
979it will be checked if that change was also changed. The mechanism to assume a
980class implements an interface just because the methods happen to match is
981brittle and leads to obscure problems, let's not do that.
982
983
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700984Using "this.variable" everywhere ~
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000985
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700986The object variables in various programming languages can often be accessed in
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000987different ways, depending on the location. Sometimes "this." has to be
988prepended to avoid ambiguity. They are usually declared without "this.".
989That is quite inconsistent and sometimes confusing.
990
991A very common issue is that in the constructor the arguments use the same name
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700992as the object variable. Then for these variables "this." needs to be prefixed
993in the body, while for other variables this is not needed and often omitted.
994This leads to a mix of variables with and without "this.", which is
995inconsistent.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000996
997For |Vim9| classes the "this." prefix is always used. Also for declaring the
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700998variables. Simple and consistent. When looking at the code inside a class
999it's also directly clear which variable references are object variables and
1000which aren't.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001001
1002
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001003Using class variables ~
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001004
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001005Using "static variable" to declare a class variable is very common, nothing
1006new here. In |Vim9| script these can be accessed directly by their name.
1007Very much like how a script-local variable can be used in a method. Since
1008object variables are always accessed with "this." prepended, it's also quickly
1009clear what kind of variable it is.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001010
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001011TypeScript prepends the class name before the class variable name, also inside
1012the class. This has two problems: The class name can be rather long, taking
1013up quite a bit of space, and when the class is renamed all these places need
1014to be changed too.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001015
1016
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001017Declaring object and class variables ~
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +00001018
1019The main choice is whether to use "var" as with variable declarations.
1020TypeScript does not use it: >
1021 class Point {
1022 x: number;
1023 y = 0;
1024 }
1025
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001026Following that Vim object variables could be declared like this: >
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +00001027 class Point
1028 this.x: number
1029 this.y = 0
1030 endclass
1031
1032Some users pointed out that this looks more like an assignment than a
1033declaration. Adding "var" changes that: >
1034 class Point
Doug Kearns74da0ee2023-12-14 20:26:26 +01001035 var x: number
1036 var y = 0
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +00001037 endclass
1038
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001039We also need to be able to declare class variables using the "static" keyword.
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +00001040There we can also choose to leave out "var": >
1041 class Point
Doug Kearns74da0ee2023-12-14 20:26:26 +01001042 var x: number
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +00001043 static count = 0
1044 endclass
1045
1046Or do use it, before "static": >
1047 class Point
Doug Kearns74da0ee2023-12-14 20:26:26 +01001048 var x: number
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +00001049 var static count = 0
1050 endclass
1051
1052Or after "static": >
1053 class Point
Doug Kearns74da0ee2023-12-14 20:26:26 +01001054 var x: number
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +00001055 static var count = 0
1056 endclass
1057
1058This is more in line with "static def Func()".
1059
1060There is no clear preference whether to use "var" or not. The two main
1061reasons to leave it out are:
Doug Kearns74da0ee2023-12-14 20:26:26 +010010621. TypeScript and other popular languages do not use it.
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +000010632. Less clutter.
1064
Doug Kearns74da0ee2023-12-14 20:26:26 +01001065However, it is more common for languages to reuse their general variable and
1066function declaration syntax for class/object variables and methods. Vim9 also
1067reuses the general function declaration syntax for methods. So, for the sake
1068of consistency, we require "var" in these declarations.
1069
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +00001070
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001071Using "ClassName.new()" to construct an object ~
1072
1073Many languages use the "new" operator to create an object, which is actually
1074kind of strange, since the constructor is defined as a method with arguments,
1075not a command. TypeScript also has the "new" keyword, but the method is
1076called "constructor()", it is hard to see the relation between the two.
1077
1078In |Vim9| script the constructor method is called new(), and it is invoked as
1079new(), simple and straightforward. Other languages use "new ClassName()",
1080while there is no ClassName() method, it's a method by another name in the
1081class called ClassName. Quite confusing.
1082
1083
Ernie Rael03042a22023-11-11 08:53:32 +01001084Vim9class access modes ~
1085 *vim9-access-modes*
1086The variable access modes, and their meaning, supported by Vim9class are
1087 |public-variable| read and write from anywhere
1088 |read-only-variable| read from anywhere, write from inside the
1089 class and sub-classes
1090 |protected-variable| read and write from inside the class and
1091 sub-classes
1092
1093The method access modes are similar, but without the read-only mode.
1094
1095
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001096Default read access to object variables ~
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001097
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001098Some users will remark that the access rules for object variables are
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001099asymmetric. Well, that is intentional. Changing a value is a very different
1100action than reading a value. The read operation has no side effects, it can
1101be done any number of times without affecting the object. Changing the value
1102can have many side effects, and even have a ripple effect, affecting other
1103objects.
1104
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001105When adding object variables one usually doesn't think much about this, just
1106get the type right. And normally the values are set in the new() method.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001107Therefore defaulting to read access only "just works" in most cases. And when
1108directly writing you get an error, which makes you wonder if you actually want
1109to allow that. This helps writing code with fewer mistakes.
1110
1111
Ernie Rael03042a22023-11-11 08:53:32 +01001112Making object variables protected with an underscore ~
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001113
Ernie Rael03042a22023-11-11 08:53:32 +01001114When an object variable is protected, it can only be read and changed inside
1115the class (and in sub-classes), then it cannot be used outside of the class.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001116Prepending an underscore is a simple way to make that visible. Various
1117programming languages have this as a recommendation.
1118
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001119In case you change your mind and want to make the object variable accessible
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001120outside of the class, you will have to remove the underscore everywhere.
1121Since the name only appears in the class (and sub-classes) they will be easy
1122to find and change.
1123
1124The other way around is much harder: you can easily prepend an underscore to
Ernie Rael03042a22023-11-11 08:53:32 +01001125the object variable inside the class to make it protected, but any usage
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001126elsewhere you will have to track down and change. You may have to make it a
1127"set" method call. This reflects the real world problem that taking away
1128access requires work to be done for all places where that access exists.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001129
Ernie Rael03042a22023-11-11 08:53:32 +01001130An alternative would have been using the "protected" keyword, just like
1131"public" changes the access in the other direction. Well, that's just to
1132reduce the number of keywords.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001133
1134
Ernie Rael03042a22023-11-11 08:53:32 +01001135No private object variables ~
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001136
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001137Some languages provide several ways to control access to object variables.
1138The most known is "protected", and the meaning varies from language to
Ernie Rael03042a22023-11-11 08:53:32 +01001139language. Others are "shared", "private", "package" and even "friend".
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001140
1141These rules make life more difficult. That can be justified in projects where
1142many people work on the same, complex code where it is easy to make mistakes.
1143Especially when refactoring or other changes to the class model.
1144
1145The Vim scripts are expected to be used in a plugin, with just one person or a
1146small team working on it. Complex rules then only make it more complicated,
Bram Moolenaar71badf92023-04-22 22:40:14 +01001147the extra safety provided by the rules isn't really needed. Let's just keep
1148it simple and not specify access details.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001149
1150
1151==============================================================================
1152
115310. To be done later
1154
1155Can a newSomething() constructor invoke another constructor? If yes, what are
1156the restrictions?
1157
1158Thoughts:
1159- Generics for a class: `class <Tkey, Tentry>`
1160- Generics for a function: `def <Tkey> GetLast(key: Tkey)`
1161- Mixins: not sure if that is useful, leave out for simplicity.
1162
1163Some things that look like good additions:
1164- For testing: Mock mechanism
1165
1166An important class to be provided is "Promise". Since Vim is single
1167threaded, connecting asynchronous operations is a natural way of allowing
1168plugins to do their work without blocking the user. It's a uniform way to
1169invoke callbacks and handle timeouts and errors.
1170
1171
1172 vim:tw=78:ts=8:noet:ft=help:norl: