blob: b71e95f42562886604313c7a73ecc3437c345ed7 [file] [log] [blame]
Yegappan Lakshmanan49cdd622023-12-24 11:01:23 +01001*vim9class.txt* For Vim version 9.0. Last change: 2023 Dec 24
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00002
3
4 VIM REFERENCE MANUAL by Bram Moolenaar
5
6
Yegappan Lakshmanan49cdd622023-12-24 11:01:23 +01007Vim9 classes, objects, interfaces, types and enums. *vim9-class*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00008
91. Overview |Vim9-class-overview|
102. A simple class |Vim9-simple-class|
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200113. Class variables and methods |Vim9-class-member|
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000124. Using an abstract class |Vim9-abstract-class|
135. Using an interface |Vim9-using-interface|
146. More class details |Vim9-class|
157. Type definition |Vim9-type|
168. Enum |Vim9-enum|
Bram Moolenaarc1c365c2022-12-04 20:13:24 +000017
189. Rationale
1910. To be done later
20
21==============================================================================
22
231. Overview *Vim9-class-overview*
24
25The fancy term is "object-oriented programming". You can find lots of study
Bram Moolenaarbe4e0162023-02-02 13:59:48 +000026material on this subject. Here we document what |Vim9| script provides,
27assuming you know the basics already. Added are helpful hints about how to
Yegappan Lakshmanan0ab500d2023-10-21 11:59:42 +020028use this functionality effectively. Vim9 classes and objects cannot be used
29in legacy Vim scripts and legacy functions.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +000030
31The basic item is an object:
32- An object stores state. It contains one or more variables that can each
33 have a value.
Bram Moolenaarbe4e0162023-02-02 13:59:48 +000034- An object provides functions that use and manipulate its state. These
Bram Moolenaarc1c365c2022-12-04 20:13:24 +000035 functions are invoked "on the object", which is what sets it apart from the
36 traditional separation of data and code that manipulates the data.
37- An object has a well defined interface, with typed member variables and
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -070038 methods.
Bram Moolenaarbe4e0162023-02-02 13:59:48 +000039- Objects are created from a class and all objects have the same interface.
40 This does not change at runtime, it is not dynamic.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +000041
42An object can only be created by a class. A class provides:
43- A new() method, the constructor, which returns an object for the class.
44 This method is invoked on the class name: MyClass.new().
Bram Moolenaarbe4e0162023-02-02 13:59:48 +000045- State shared by all objects of the class: class variables (class members).
Bram Moolenaarc1c365c2022-12-04 20:13:24 +000046- A hierarchy of classes, with super-classes and sub-classes, inheritance.
47
48An interface is used to specify properties of an object:
49- An object can declare several interfaces that it implements.
50- Different objects implementing the same interface can be used the same way.
51
52The class hierarchy allows for single inheritance. Otherwise interfaces are
53to be used where needed.
54
55
56Class modeling ~
57
58You can model classes any way you like. Keep in mind what you are building,
59don't try to model the real world. This can be confusing, especially because
60teachers use real-world objects to explain class relations and you might think
61your model should therefore reflect the real world. It doesn't! The model
62should match your purpose.
63
Bram Moolenaarbe4e0162023-02-02 13:59:48 +000064Keep in mind that composition (an object contains other objects) is often
65better than inheritance (an object extends another object). Don't waste time
66trying to find the optimal class model. Or waste time discussing whether a
67square is a rectangle or that a rectangle is a square. It doesn't matter.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +000068
69
70==============================================================================
71
722. A simple class *Vim9-simple-class*
73
Bram Moolenaarbe4e0162023-02-02 13:59:48 +000074Let's start with a simple example: a class that stores a text position (see
75below for how to do this more efficiently): >
Bram Moolenaarc1c365c2022-12-04 20:13:24 +000076
77 class TextPosition
Doug Kearns74da0ee2023-12-14 20:26:26 +010078 var lnum: number
79 var col: number
Bram Moolenaarc1c365c2022-12-04 20:13:24 +000080
81 def new(lnum: number, col: number)
82 this.lnum = lnum
83 this.col = col
84 enddef
85
86 def SetLnum(lnum: number)
87 this.lnum = lnum
88 enddef
89
90 def SetCol(col: number)
91 this.col = col
92 enddef
93
94 def SetPosition(lnum: number, col: number)
95 this.lnum = lnum
96 this.col = col
97 enddef
98 endclass
Bram Moolenaar7db29e42022-12-11 15:53:04 +000099< *object* *Object*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000100You can create an object from this class with the new() method: >
101
102 var pos = TextPosition.new(1, 1)
errael1d4fcfe2023-12-21 08:34:15 -0800103<
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700104The object variables "lnum" and "col" can be accessed directly: >
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000105
106 echo $'The text position is ({pos.lnum}, {pos.col})'
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000107< *E1317* *E1327*
errael1d4fcfe2023-12-21 08:34:15 -0800108If you have been using other object-oriented languages you will notice that in
109Vim, within a class definition, the object members are consistently referred
110to with the "this." prefix. This is different from languages like Java and
111TypeScript. The naming convention makes the object members easy to spot.
112Also, when a variable does not have the "this." prefix you know it is not an
113object variable.
114 *E1411*
115From outside the class definition, access an object's methods and variables by
116using the object name followed by a dot following by the member: >
117
118 pos.lnum
119 pos.setCol(10)
120<
121 *E1405* *E1406*
122A class name cannot be used as an expression. A class name cannot be used in
123the left-hand-side of an assignment.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000124
125
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700126Object variable write access ~
Ernie Rael03042a22023-11-11 08:53:32 +0100127 *read-only-variable*
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700128Now try to change an object variable directly: >
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000129
130 pos.lnum = 9
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000131< *E1335*
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700132This will give you an error! That is because by default object variables can
133be read but not set. That's why the TextPosition class provides a method for
134it: >
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000135
136 pos.SetLnum(9)
137
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700138Allowing to read but not set an object variable is the most common and safest
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000139way. Most often there is no problem using a value, while setting a value may
140have side effects that need to be taken care of. In this case, the SetLnum()
141method could check if the line number is valid and either give an error or use
142the closest valid value.
Ernie Rael03042a22023-11-11 08:53:32 +0100143 *:public* *public-variable* *E1331*
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700144If you don't care about side effects and want to allow the object variable to
145be changed at any time, you can make it public: >
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000146
147 public this.lnum: number
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000148 public this.col: number
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000149
150Now you don't need the SetLnum(), SetCol() and SetPosition() methods, setting
151"pos.lnum" directly above will no longer give an error.
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200152 *E1326*
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700153If you try to set an object variable that doesn't exist you get an error: >
Bram Moolenaarf1dcd142022-12-31 15:30:45 +0000154 pos.other = 9
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200155< E1326: Member not found on object "TextPosition": other ~
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000156
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200157 *E1376*
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700158A object variable cannot be accessed using the class name.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000159
Ernie Rael03042a22023-11-11 08:53:32 +0100160Protected variables ~
161 *protected-variable* *E1332* *E1333*
162On the other hand, if you do not want the object variables to be read directly
163from outside the class or its sub-classes, you can make them protected. This
164is done by prefixing an underscore to the name: >
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000165
Doug Kearns74da0ee2023-12-14 20:26:26 +0100166 var _lnum: number
167 var _col number
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000168
Ernie Rael03042a22023-11-11 08:53:32 +0100169Now you need to provide methods to get the value of the protected variables.
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000170These are commonly called getters. We recommend using a name that starts with
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000171"Get": >
172
173 def GetLnum(): number
174 return this._lnum
175 enddef
176
177 def GetCol() number
178 return this._col
179 enddef
180
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700181This example isn't very useful, the variables might as well have been public.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000182It does become useful if you check the value. For example, restrict the line
183number to the total number of lines: >
184
185 def GetLnum(): number
186 if this._lnum > this._lineCount
187 return this._lineCount
188 endif
189 return this._lnum
190 enddef
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200191<
Ernie Rael03042a22023-11-11 08:53:32 +0100192Protected methods ~
193 *protected-method* *E1366*
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +0200194If you want object methods to be accessible only from other methods of the
195same class and not used from outside the class, then you can make them
Ernie Rael03042a22023-11-11 08:53:32 +0100196protected. This is done by prefixing the method name with an underscore: >
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +0200197
198 class SomeClass
199 def _Foo(): number
200 return 10
201 enddef
202 def Bar(): number
203 return this._Foo()
204 enddef
205 endclass
206<
Ernie Rael03042a22023-11-11 08:53:32 +0100207Accessing a protected method outside the class will result in an error (using
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +0200208the above class): >
209
210 var a = SomeClass.new()
211 a._Foo()
212<
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000213Simplifying the new() method ~
Yegappan Lakshmanan413f8392023-09-28 22:46:37 +0200214 *new()* *constructor*
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700215Many constructors take values for the object variables. Thus you very often
216see this pattern: >
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000217
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000218 class SomeClass
Doug Kearns74da0ee2023-12-14 20:26:26 +0100219 var lnum: number
220 var col: number
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000221
222 def new(lnum: number, col: number)
223 this.lnum = lnum
224 this.col = col
225 enddef
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000226 endclass
h-eastdb385522023-09-28 22:18:19 +0200227<
228 *E1390*
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700229Not only is this text you need to write, it also has the type of each
Dominique Pellé17dca3c2023-12-14 20:36:32 +0100230variable twice. Since this is so common a shorter way to write new() is
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700231provided: >
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000232
233 def new(this.lnum, this.col)
234 enddef
235
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700236The semantics are easy to understand: Providing the object variable name,
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000237including "this.", as the argument to new() means the value provided in the
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700238new() call is assigned to that object variable. This mechanism comes from the
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000239Dart language.
240
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700241Putting together this way of using new() and making the variables public
242results in a much shorter class definition than what we started with: >
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000243
244 class TextPosition
Doug Kearns74da0ee2023-12-14 20:26:26 +0100245 public var lnum: number
246 public var col: number
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000247
248 def new(this.lnum, this.col)
249 enddef
250
251 def SetPosition(lnum: number, col: number)
252 this.lnum = lnum
253 this.col = col
254 enddef
255 endclass
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000256
257The sequence of constructing a new object is:
2581. Memory is allocated and cleared. All values are zero/false/empty.
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07002592. For each declared object variable that has an initializer, the expression
260 is evaluated and assigned to the variable. This happens in the sequence
261 the variables are declared in the class.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00002623. Arguments in the new() method in the "this.name" form are assigned.
2634. The body of the new() method is executed.
264
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000265If the class extends a parent class, the same thing happens. In the second
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700266step the object variables of the parent class are initialized first. There is
267no need to call "super()" or "new()" on the parent.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000268
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200269 *E1365*
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +0200270When defining the new() method the return type should not be specified. It
271always returns an object of the class.
272
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200273 *E1386*
274When invoking an object method, the method name should be preceded by the
Dominique Pellé17dca3c2023-12-14 20:36:32 +0100275object variable name. An object method cannot be invoked using the class
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200276name.
277
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000278==============================================================================
279
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02002803. Class Variables and Methods *Vim9-class-member*
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000281
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200282 *:static* *E1337* *E1338* *E1368*
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000283Class members are declared with "static". They are used by the name without a
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200284prefix in the class where they are defined: >
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000285
286 class OtherThing
Doug Kearns74da0ee2023-12-14 20:26:26 +0100287 var size: number
288 static var totalSize: number
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000289
290 def new(this.size)
291 totalSize += this.size
292 enddef
293 endclass
294< *E1340* *E1341*
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700295Since the name is used as-is, shadowing the name by a method argument name
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000296or local variable name is not allowed.
297
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200298 *E1374* *E1375* *E1384* *E1385*
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200299To access a class member outside of the class where it is defined, the class
300name prefix must be used. A class member cannot be accessed using an object.
301
Ernie Rael03042a22023-11-11 08:53:32 +0100302Just like object members the access can be made protected by using an
303underscore as the first character in the name, and it can be made public by
304prefixing "public": >
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000305
306 class OtherThing
Doug Kearns74da0ee2023-12-14 20:26:26 +0100307 static var total: number # anybody can read, only class can write
308 static var _sum: number # only class can read and write
309 public static var result: number # anybody can read and write
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000310 endclass
311<
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200312 *class-method*
313Class methods are also declared with "static". They can use the class
314variables but they have no access to the object variables, they cannot use the
h_eastba77bbb2023-10-03 04:47:13 +0900315"this" keyword:
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200316>
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000317 class OtherThing
Doug Kearns74da0ee2023-12-14 20:26:26 +0100318 var size: number
319 static var totalSize: number
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000320
321 # Clear the total size and return the value it had before.
322 static def ClearTotalSize(): number
323 var prev = totalSize
324 totalSize = 0
325 return prev
326 enddef
327 endclass
328
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200329Inside the class the class method can be called by name directly, outside the
330class the class name must be prefixed: `OtherThing.ClearTotalSize()`. To use
331a super class method in a child class, the class name must be prefixed.
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000332
Ernie Rael03042a22023-11-11 08:53:32 +0100333Just like object methods the access can be made protected by using an
334underscore as the first character in the method name: >
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +0200335
336 class OtherThing
337 static def _Foo()
338 echo "Foo"
339 enddef
340 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200341 _Foo()
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +0200342 enddef
343 endclass
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +0200344<
345 *E1370*
Ernie Rael4e286312023-12-24 11:03:31 +0100346Note that constructors cannot be declared as "static". They are called like a
347static but execute as an object method; they have access to "this".
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +0200348
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200349To access the class methods and class variables of a super class in an
350extended class, the class name prefix should be used just as from anywhere
351outside of the defining class: >
352
353 vim9script
354 class Vehicle
Doug Kearns74da0ee2023-12-14 20:26:26 +0100355 static var nextID: number = 1000
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200356 static def GetID(): number
357 nextID += 1
358 return nextID
359 enddef
360 endclass
361 class Car extends Vehicle
Doug Kearns74da0ee2023-12-14 20:26:26 +0100362 var myID: number
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200363 def new()
364 this.myID = Vehicle.GetID()
365 enddef
366 endclass
367<
368Class variables and methods are not inherited by a child class. A child class
369can declare a static variable or a method with the same name as the one in the
370super class. Depending on the class where the member is used the
371corresponding class member will be used. The type of the class member in a
372child class can be different from that in the super class.
373
Yegappan Lakshmananff6f0d52023-12-21 16:46:18 +0100374The double underscore (__) prefix for a class or object method name is
375reserved for future use.
376
Yegappan Lakshmanane5437c52023-12-16 14:11:19 +0100377 *object-final-variable* *E1409*
378The |:final| keyword can be used to make a class or object variable a
379constant. Examples: >
380
381 class A
382 final v1 = [1, 2] # final object variable
383 public final v2 = {x: 1} # final object variable
384 static final v3 = 'abc' # final class variable
385 public static final v4 = 0z10 # final class variable
386 endclass
387<
388A final variable can be changed only from a constructor function. Example: >
389
390 class A
391 final v1: list<number>
392 def new()
393 this.v1 = [1, 2]
394 enddef
395 endclass
396 var a = A.new()
397 echo a.v1
398<
399Note that the value of a final variable can be changed. Example: >
400
401 class A
402 public final v1 = [1, 2]
403 endclass
404 var a = A.new()
405 a.v1[0] = 6 # OK
406 a.v1->add(3) # OK
407 a.v1 = [3, 4] # Error
408<
409 *E1408*
410Final variables are not supported in an interface. A class or object method
411cannot be final.
412
413 *object-const-variable*
414The |:const| keyword can be used to make a class or object variable and the
415value a constant. Examples: >
416
417 class A
418 const v1 = [1, 2] # const object variable
419 public const v2 = {x: 1} # const object variable
420 static const v3 = 'abc' # const class variable
421 public static const v4 = 0z10 # const class variable
422 endclass
423<
424A const variable can be changed only from a constructor function. Example: >
425
426 class A
427 const v1: list<number>
428 def new()
429 this.v1 = [1, 2]
430 enddef
431 endclass
432 var a = A.new()
433 echo a.v1
434<
435A const variable and its value cannot be changed. Example: >
436
437 class A
438 public const v1 = [1, 2]
439 endclass
440 var a = A.new()
441 a.v1[0] = 6 # Error
442 a.v1->add(3) # Error
443 a.v1 = [3, 4] # Error
444<
445 *E1410*
446Const variables are not supported in an interface. A class or object method
447cannot be a const.
448
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000449==============================================================================
450
4514. Using an abstract class *Vim9-abstract-class*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000452
453An abstract class forms the base for at least one sub-class. In the class
454model one often finds that a few classes have the same properties that can be
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000455shared, but a class with these properties does not have enough state to create
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000456an object from. A sub-class must extend the abstract class and add the
457missing state and/or methods before it can be used to create objects for.
458
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000459For example, a Shape class could store a color and thickness. You cannot
460create a Shape object, it is missing the information about what kind of shape
461it is. The Shape class functions as the base for a Square and a Triangle
462class, for which objects can be created. Example: >
463
464 abstract class Shape
Doug Kearns74da0ee2023-12-14 20:26:26 +0100465 var color = Color.Black
466 var thickness = 10
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000467 endclass
468
469 class Square extends Shape
Doug Kearns74da0ee2023-12-14 20:26:26 +0100470 var size: number
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000471
472 def new(this.size)
473 enddef
474 endclass
475
476 class Triangle extends Shape
Doug Kearns74da0ee2023-12-14 20:26:26 +0100477 var base: number
478 var height: number
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000479
480 def new(this.base, this.height)
481 enddef
482 endclass
483<
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000484An abstract class is defined the same way as a normal class, except that it
485does not have any new() method. *E1359*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000486
h_east596a9f22023-11-21 21:24:23 +0900487 *abstract-method* *E1371* *E1372*
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +0200488An abstract method can be defined in an abstract class by using the "abstract"
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700489prefix when defining the method: >
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +0200490
491 abstract class Shape
492 abstract def Draw()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200493 abstract static def SetColor()
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +0200494 endclass
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200495<
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +0100496A static method in an abstract class cannot be an abstract method.
497
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200498 *E1373*
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +0200499A class extending the abstract class must implement all the abstract methods.
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200500The signature (arguments, argument types and return type) must be exactly the
Yegappan Lakshmanan26e8f7b2023-10-06 10:24:10 -0700501same. If the return type of a method is a class, then that class or one of
502its subclasses can be used in the extended method. Class methods in an
503abstract class can also be abstract methods.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000504
505==============================================================================
506
Bram Moolenaarbe4e0162023-02-02 13:59:48 +00005075. Using an interface *Vim9-using-interface*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000508
509The example above with Shape, Square and Triangle can be made more useful if
510we add a method to compute the surface of the object. For that we create the
511interface called HasSurface, which specifies one method Surface() that returns
512a number. This example extends the one above: >
513
514 abstract class Shape
Doug Kearns74da0ee2023-12-14 20:26:26 +0100515 var color = Color.Black
516 var thickness = 10
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000517 endclass
518
519 interface HasSurface
520 def Surface(): number
521 endinterface
522
523 class Square extends Shape implements HasSurface
Doug Kearns74da0ee2023-12-14 20:26:26 +0100524 var size: number
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000525
526 def new(this.size)
527 enddef
528
529 def Surface(): number
530 return this.size * this.size
531 enddef
532 endclass
533
534 class Triangle extends Shape implements HasSurface
Doug Kearns74da0ee2023-12-14 20:26:26 +0100535 var base: number
536 var height: number
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000537
538 def new(this.base, this.height)
539 enddef
540
541 def Surface(): number
542 return this.base * this.height / 2
543 enddef
544 endclass
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200545<
546 *E1348* *E1349* *E1367* *E1382* *E1383*
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000547If a class declares to implement an interface, all the items specified in the
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200548interface must appear in the class, with the same types.
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000549
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000550The interface name can be used as a type: >
551
552 var shapes: list<HasSurface> = [
553 Square.new(12),
554 Triangle.new(8, 15),
555 ]
556 for shape in shapes
557 echo $'the surface is {shape.Surface()}'
558 endfor
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200559<
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200560 *E1378* *E1379* *E1380* *E1387*
561An interface can contain only object methods and read-only object variables.
Ernie Rael03042a22023-11-11 08:53:32 +0100562An interface cannot contain read-write or protected object variables,
563protected object methods, class variables and class methods.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000564
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200565An interface can extend another interface using "extends". The sub-interface
566inherits all the instance variables and methods from the super interface.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000567
568==============================================================================
569
Bram Moolenaarbe4e0162023-02-02 13:59:48 +00005706. More class details *Vim9-class* *Class* *class*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000571
572Defining a class ~
573 *:class* *:endclass* *:abstract*
574A class is defined between `:class` and `:endclass`. The whole class is
575defined in one script file. It is not possible to add to a class later.
576
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000577A class can only be defined in a |Vim9| script file. *E1316*
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000578A class cannot be defined inside a function.
579
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000580It is possible to define more than one class in a script file. Although it
581usually is better to export only one main class. It can be useful to define
582types, enums and helper classes though.
583
584The `:abstract` keyword may be prefixed and `:export` may be used. That gives
585these variants: >
586
587 class ClassName
588 endclass
589
590 export class ClassName
591 endclass
592
593 abstract class ClassName
594 endclass
595
596 export abstract class ClassName
597 endclass
598<
599 *E1314*
600The class name should be CamelCased. It must start with an uppercase letter.
601That avoids clashing with builtin types.
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000602 *E1315*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000603After the class name these optional items can be used. Each can appear only
604once. They can appear in any order, although this order is recommended: >
605 extends ClassName
606 implements InterfaceName, OtherInterface
607 specifies SomeInterface
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200608< *E1355* *E1369*
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700609Each variable and method name can be used only once. It is not possible to
610define a method with the same name and different type of arguments. It is not
Ernie Rael03042a22023-11-11 08:53:32 +0100611possible to use a public and protected member variable with the same name. A
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700612object variable name used in a super class cannot be reused in a child class.
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000613
614
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700615Object Variable Initialization ~
Ernie Rael03042a22023-11-11 08:53:32 +0100616
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700617If the type of a variable is not explicitly specified in a class, then it is
618set to "any" during class definition. When an object is instantiated from the
619class, then the type of the variable is set.
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200620
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +0200621The following reserved keyword names cannot be used as an object or class
622variable name: "super", "this", "true", "false", "null", "null_blob",
623"null_dict", "null_function", "null_list", "null_partial", "null_string",
624"null_channel" and "null_job".
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200625
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000626Extending a class ~
627 *extends*
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000628A class can extend one other class. *E1352* *E1353* *E1354*
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000629The basic idea is to build on top of an existing class, add properties to it.
630
631The extended class is called the "base class" or "super class". The new class
632is called the "child class".
633
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700634Object variables from the base class are all taken over by the child class. It
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000635is not possible to override them (unlike some other languages).
636
637 *E1356* *E1357* *E1358*
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +0200638Object methods of the base class can be overruled. The signature (arguments,
Yegappan Lakshmanan26e8f7b2023-10-06 10:24:10 -0700639argument types and return type) must be exactly the same. If the return type
640of a method is a class, then that class or one of its subclasses can be used
641in the extended method. The method of the base class can be called by
642prefixing "super.".
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000643
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200644 *E1377*
Ernie Rael03042a22023-11-11 08:53:32 +0100645The access level of a method (public or protected) in a child class should be
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200646the same as the super class.
647
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000648Other object methods of the base class are taken over by the child class.
649
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700650Class methods, including methods starting with "new", can be overruled, like
651with object methods. The method on the base class can be called by prefixing
652the name of the class (for class methods) or "super.".
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000653
654Unlike other languages, the constructor of the base class does not need to be
655invoked. In fact, it cannot be invoked. If some initialization from the base
656class also needs to be done in a child class, put it in an object method and
657call that method from every constructor().
658
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700659If the base class did not specify a new() method then one was automatically
660created. This method will not be taken over by the child class. The child
661class can define its own new() method, or, if there isn't one, a new() method
662will be added automatically.
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000663
664
665A class implementing an interface ~
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200666 *implements* *E1346* *E1347* *E1389*
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000667A class can implement one or more interfaces. The "implements" keyword can
668only appear once *E1350* . Multiple interfaces can be specified, separated by
669commas. Each interface name can appear only once. *E1351*
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000670
671
672A class defining an interface ~
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000673 *specifies*
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700674A class can declare its interface, the object variables and methods, with a
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000675named interface. This avoids the need for separately specifying the
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000676interface, which is often done in many languages, especially Java.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000677
678
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000679Items in a class ~
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200680 *E1318* *E1325* *E1388*
Bram Moolenaardd60c362023-02-27 15:49:53 +0000681Inside a class, in between `:class` and `:endclass`, these items can appear:
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700682- An object variable declaration: >
Doug Kearns74da0ee2023-12-14 20:26:26 +0100683 var _protectedVariableName: memberType
684 var readonlyVariableName: memberType
685 public var readwriteVariableName: memberType
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700686- A class variable declaration: >
Doug Kearns74da0ee2023-12-14 20:26:26 +0100687 static var _protectedClassVariableName: memberType
688 static var readonlyClassVariableName: memberType
689 static var public readwriteClassVariableName: memberType
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000690- A constructor method: >
Bram Moolenaar938ae282023-02-20 20:44:55 +0000691 def new(arguments)
692 def newName(arguments)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200693- A class method: >
694 static def SomeMethod(arguments)
Ernie Rael03042a22023-11-11 08:53:32 +0100695 static def _ProtectedMethod(arguments)
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000696- An object method: >
Bram Moolenaar938ae282023-02-20 20:44:55 +0000697 def SomeMethod(arguments)
Ernie Rael03042a22023-11-11 08:53:32 +0100698 def _ProtectedMethod(arguments)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200699
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700700For the object variable the type must be specified. The best way is to do
701this explicitly with ": {type}". For simple types you can also use an
702initializer, such as "= 123", and Vim will see that the type is a number.
703Avoid doing this for more complex types and when the type will be incomplete.
704For example: >
Doug Kearns74da0ee2023-12-14 20:26:26 +0100705 var nameList = []
Bram Moolenaarf1dcd142022-12-31 15:30:45 +0000706This specifies a list, but the item type is unknown. Better use: >
Doug Kearns74da0ee2023-12-14 20:26:26 +0100707 var nameList: list<string>
Bram Moolenaarf1dcd142022-12-31 15:30:45 +0000708The initialization isn't needed, the list is empty by default.
709 *E1330*
710Some types cannot be used, such as "void", "null" and "v:none".
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000711
712
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000713Defining an interface ~
714 *:interface* *:endinterface*
715An interface is defined between `:interface` and `:endinterface`. It may be
716prefixed with `:export`: >
717
718 interface InterfaceName
719 endinterface
720
721 export interface InterfaceName
722 endinterface
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000723< *E1344*
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700724An interface can declare object variables, just like in a class but without
725any initializer.
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000726 *E1345*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000727An interface can declare methods with `:def`, including the arguments and
728return type, but without the body and without `:enddef`. Example: >
729
730 interface HasSurface
Doug Kearns74da0ee2023-12-14 20:26:26 +0100731 var size: number
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000732 def Surface(): number
733 endinterface
734
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000735An interface name must start with an uppercase letter. *E1343*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000736The "Has" prefix can be used to make it easier to guess this is an interface
737name, with a hint about what it provides.
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000738An interface can only be defined in a |Vim9| script file. *E1342*
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200739An interface cannot "implement" another interface but it can "extend" another
740interface. *E1381*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000741
742
Bram Moolenaar938ae282023-02-20 20:44:55 +0000743null object ~
744
Bram Moolenaardd60c362023-02-27 15:49:53 +0000745When a variable is declared to have the type of an object, but it is not
Bram Moolenaar938ae282023-02-20 20:44:55 +0000746initialized, the value is null. When trying to use this null object Vim often
747does not know what class was supposed to be used. Vim then cannot check if
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700748a variable name is correct and you will get an "Using a null object" error,
h_eastba77bbb2023-10-03 04:47:13 +0900749even when the variable name is invalid. *E1360* *E1362*
Bram Moolenaar938ae282023-02-20 20:44:55 +0000750
751
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000752Default constructor ~
Yegappan Lakshmanan413f8392023-09-28 22:46:37 +0200753 *default-constructor*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000754In case you define a class without a new() method, one will be automatically
755defined. This default constructor will have arguments for all the object
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700756variables, in the order they were specified. Thus if your class looks like: >
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000757
758 class AutoNew
Doug Kearns74da0ee2023-12-14 20:26:26 +0100759 var name: string
760 var age: number
761 var gender: Gender
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000762 endclass
763
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700764Then the default constructor will be: >
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000765
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000766 def new(this.name = v:none, this.age = v:none, this.gender = v:none)
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000767 enddef
768
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000769The "= v:none" default values make the arguments optional. Thus you can also
770call `new()` without any arguments. No assignment will happen and the default
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700771value for the object variables will be used. This is a more useful example,
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000772with default values: >
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000773
774 class TextPosition
Doug Kearns74da0ee2023-12-14 20:26:26 +0100775 var lnum: number = 1
776 var col: number = 1
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000777 endclass
778
779If you want the constructor to have mandatory arguments, you need to write it
780yourself. For example, if for the AutoNew class above you insist on getting
781the name, you can define the constructor like this: >
782
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000783 def new(this.name, this.age = v:none, this.gender = v:none)
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000784 enddef
Yegappan Lakshmanan563e6442023-12-05 08:19:06 -0800785<
786When using the default new() method, if the order of the object variables in
787the class is changed later, then all the callers of the default new() method
788needs to change. To avoid this, the new() method can be explicitly defined
789without any arguments.
790
791 *E1328*
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000792Note that you cannot use another default value than "v:none" here. If you
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700793want to initialize the object variables, do it where they are declared. This
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000794way you only need to look in one place for the default values.
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000795
Ernie Rael03042a22023-11-11 08:53:32 +0100796All object variables will be used in the default constructor, including
797protected access ones.
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000798
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700799If the class extends another one, the object variables of that class will come
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000800first.
801
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000802
803Multiple constructors ~
804
805Normally a class has just one new() constructor. In case you find that the
806constructor is often called with the same arguments you may want to simplify
807your code by putting those arguments into a second constructor method. For
808example, if you tend to use the color black a lot: >
809
810 def new(this.garment, this.color, this.size)
811 enddef
812 ...
813 var pants = new(Garment.pants, Color.black, "XL")
814 var shirt = new(Garment.shirt, Color.black, "XL")
815 var shoes = new(Garment.shoes, Color.black, "45")
816
817Instead of repeating the color every time you can add a constructor that
818includes it: >
819
820 def newBlack(this.garment, this.size)
821 this.color = Color.black
822 enddef
823 ...
824 var pants = newBlack(Garment.pants, "XL")
825 var shirt = newBlack(Garment.shirt, "XL")
826 var shoes = newBlack(Garment.shoes, "9.5")
827
828Note that the method name must start with "new". If there is no method called
829"new()" then the default constructor is added, even though there are other
830constructor methods.
831
832
833==============================================================================
834
Bram Moolenaarbe4e0162023-02-02 13:59:48 +00008357. Type definition *Vim9-type* *:type*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000836
Yegappan Lakshmanan2a71b542023-12-14 20:03:03 +0100837 *E1393* *E1395* *E1396* *E1397* *E1398*
838A type definition is giving a name to a type specification. This is also
839known as a "type alias". The type alias can be used wherever a built-in type
840can be used. Example: >
Yegappan Lakshmanan26e8f7b2023-10-06 10:24:10 -0700841
Yegappan Lakshmanan2a71b542023-12-14 20:03:03 +0100842 type ListOfStrings = list<string>
843 var s: ListOfStrings = ['a', 'b']
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000844
Yegappan Lakshmanan2a71b542023-12-14 20:03:03 +0100845 def ProcessStr(str: ListOfStrings): ListOfStrings
846 return str
847 enddef
848 echo ProcessStr(s)
849<
850 *E1394*
851A type alias name must start with an upper case character. Only existing
852types can be aliased.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000853
Yegappan Lakshmanan2a71b542023-12-14 20:03:03 +0100854 *E1399*
855A type alias can be created only at the script level and not inside a
856function. A type alias can be exported and used across scripts.
857
858 *E1400* *E1401* *E1402* *E1403* *E1407*
859A type alias cannot be used as an expression. A type alias cannot be used in
860the left-hand-side of an assignment.
861
862For a type alias name, the |typename()| function returns the type that is
863aliased: >
864
865 type ListOfStudents = list<dict<any>>
866 echo typename(ListOfStudents)
867 typealias<list<dict<any>>>
868<
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000869==============================================================================
870
Bram Moolenaarbe4e0162023-02-02 13:59:48 +00008718. Enum *Vim9-enum* *:enum* *:endenum*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000872
Yegappan Lakshmanan26e8f7b2023-10-06 10:24:10 -0700873{not implemented yet}
874
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000875An enum is a type that can have one of a list of values. Example: >
876
877 :enum Color
878 White
879 Red
880 Green
881 Blue
882 Black
883 :endenum
884
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000885
886==============================================================================
887
8889. Rationale
889
890Most of the choices for |Vim9| classes come from popular and recently
891developed languages, such as Java, TypeScript and Dart. The syntax has been
892made to fit with the way Vim script works, such as using `endclass` instead of
893using curly braces around the whole class.
894
895Some common constructs of object-oriented languages were chosen very long ago
896when this kind of programming was still new, and later found to be
897sub-optimal. By this time those constructs were widely used and changing them
898was not an option. In Vim we do have the freedom to make different choices,
899since classes are completely new. We can make the syntax simpler and more
900consistent than what "old" languages use. Without diverting too much, it
901should still mostly look like what you know from existing languages.
902
903Some recently developed languages add all kinds of fancy features that we
904don't need for Vim. But some have nice ideas that we do want to use.
905Thus we end up with a base of what is common in popular languages, dropping
906what looks like a bad idea, and adding some nice features that are easy to
907understand.
908
909The main rules we use to make decisions:
910- Keep it simple.
911- No surprises, mostly do what other languages are doing.
912- Avoid mistakes from the past.
913- Avoid the need for the script writer to consult the help to understand how
914 things work, most things should be obvious.
915- Keep it consistent.
916- Aim at an average size plugin, not at a huge project.
917
918
919Using new() for the constructor ~
920
921Many languages use the class name for the constructor method. A disadvantage
922is that quite often this is a long name. And when changing the class name all
923constructor methods need to be renamed. Not a big deal, but still a
924disadvantage.
925
926Other languages, such as TypeScript, use a specific name, such as
927"constructor()". That seems better. However, using "new" or "new()" to
928create a new object has no obvious relation with "constructor()".
929
930For |Vim9| script using the same method name for all constructors seemed like
931the right choice, and by calling it new() the relation between the caller and
932the method being called is obvious.
933
934
935No overloading of the constructor ~
936
937In Vim script, both legacy and |Vim9| script, there is no overloading of
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700938methods. That means it is not possible to use the same method name with
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000939different types of arguments. Therefore there also is only one new()
940constructor.
941
942With |Vim9| script it would be possible to support overloading, since
943arguments are typed. However, this gets complicated very quickly. Looking at
944a new() call one has to inspect the types of the arguments to know which of
945several new() methods is actually being called. And that can require
946inspecting quite a bit of code. For example, if one of the arguments is the
947return value of a method, you need to find that method to see what type it is
948returning.
949
950Instead, every constructor has to have a different name, starting with "new".
951That way multiple constructors with different arguments are possible, while it
952is very easy to see which constructor is being used. And the type of
953arguments can be properly checked.
954
955
956No overloading of methods ~
957
958Same reasoning as for the constructor: It is often not obvious what type
959arguments have, which would make it difficult to figure out what method is
960actually being called. Better just give the methods a different name, then
961type checking will make sure it works as you intended. This rules out
962polymorphism, which we don't really need anyway.
963
964
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000965Single inheritance and interfaces ~
966
967Some languages support multiple inheritance. Although that can be useful in
968some cases, it makes the rules of how a class works quite complicated.
969Instead, using interfaces to declare what is supported is much simpler. The
970very popular Java language does it this way, and it should be good enough for
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000971Vim. The "keep it simple" rule applies here.
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000972
973Explicitly declaring that a class supports an interface makes it easy to see
974what a class is intended for. It also makes it possible to do proper type
975checking. When an interface is changed any class that declares to implement
976it will be checked if that change was also changed. The mechanism to assume a
977class implements an interface just because the methods happen to match is
978brittle and leads to obscure problems, let's not do that.
979
980
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700981Using "this.variable" everywhere ~
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000982
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700983The object variables in various programming languages can often be accessed in
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000984different ways, depending on the location. Sometimes "this." has to be
985prepended to avoid ambiguity. They are usually declared without "this.".
986That is quite inconsistent and sometimes confusing.
987
988A very common issue is that in the constructor the arguments use the same name
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700989as the object variable. Then for these variables "this." needs to be prefixed
990in the body, while for other variables this is not needed and often omitted.
991This leads to a mix of variables with and without "this.", which is
992inconsistent.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000993
994For |Vim9| classes the "this." prefix is always used. Also for declaring the
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700995variables. Simple and consistent. When looking at the code inside a class
996it's also directly clear which variable references are object variables and
997which aren't.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000998
999
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001000Using class variables ~
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001001
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001002Using "static variable" to declare a class variable is very common, nothing
1003new here. In |Vim9| script these can be accessed directly by their name.
1004Very much like how a script-local variable can be used in a method. Since
1005object variables are always accessed with "this." prepended, it's also quickly
1006clear what kind of variable it is.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001007
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001008TypeScript prepends the class name before the class variable name, also inside
1009the class. This has two problems: The class name can be rather long, taking
1010up quite a bit of space, and when the class is renamed all these places need
1011to be changed too.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001012
1013
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001014Declaring object and class variables ~
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +00001015
1016The main choice is whether to use "var" as with variable declarations.
1017TypeScript does not use it: >
1018 class Point {
1019 x: number;
1020 y = 0;
1021 }
1022
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001023Following that Vim object variables could be declared like this: >
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +00001024 class Point
1025 this.x: number
1026 this.y = 0
1027 endclass
1028
1029Some users pointed out that this looks more like an assignment than a
1030declaration. Adding "var" changes that: >
1031 class Point
Doug Kearns74da0ee2023-12-14 20:26:26 +01001032 var x: number
1033 var y = 0
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +00001034 endclass
1035
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001036We also need to be able to declare class variables using the "static" keyword.
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +00001037There we can also choose to leave out "var": >
1038 class Point
Doug Kearns74da0ee2023-12-14 20:26:26 +01001039 var x: number
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +00001040 static count = 0
1041 endclass
1042
1043Or do use it, before "static": >
1044 class Point
Doug Kearns74da0ee2023-12-14 20:26:26 +01001045 var x: number
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +00001046 var static count = 0
1047 endclass
1048
1049Or after "static": >
1050 class Point
Doug Kearns74da0ee2023-12-14 20:26:26 +01001051 var x: number
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +00001052 static var count = 0
1053 endclass
1054
1055This is more in line with "static def Func()".
1056
1057There is no clear preference whether to use "var" or not. The two main
1058reasons to leave it out are:
Doug Kearns74da0ee2023-12-14 20:26:26 +010010591. TypeScript and other popular languages do not use it.
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +000010602. Less clutter.
1061
Doug Kearns74da0ee2023-12-14 20:26:26 +01001062However, it is more common for languages to reuse their general variable and
1063function declaration syntax for class/object variables and methods. Vim9 also
1064reuses the general function declaration syntax for methods. So, for the sake
1065of consistency, we require "var" in these declarations.
1066
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +00001067
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001068Using "ClassName.new()" to construct an object ~
1069
1070Many languages use the "new" operator to create an object, which is actually
1071kind of strange, since the constructor is defined as a method with arguments,
1072not a command. TypeScript also has the "new" keyword, but the method is
1073called "constructor()", it is hard to see the relation between the two.
1074
1075In |Vim9| script the constructor method is called new(), and it is invoked as
1076new(), simple and straightforward. Other languages use "new ClassName()",
1077while there is no ClassName() method, it's a method by another name in the
1078class called ClassName. Quite confusing.
1079
1080
Ernie Rael03042a22023-11-11 08:53:32 +01001081Vim9class access modes ~
1082 *vim9-access-modes*
1083The variable access modes, and their meaning, supported by Vim9class are
1084 |public-variable| read and write from anywhere
1085 |read-only-variable| read from anywhere, write from inside the
1086 class and sub-classes
1087 |protected-variable| read and write from inside the class and
1088 sub-classes
1089
1090The method access modes are similar, but without the read-only mode.
1091
1092
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001093Default read access to object variables ~
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001094
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001095Some users will remark that the access rules for object variables are
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001096asymmetric. Well, that is intentional. Changing a value is a very different
1097action than reading a value. The read operation has no side effects, it can
1098be done any number of times without affecting the object. Changing the value
1099can have many side effects, and even have a ripple effect, affecting other
1100objects.
1101
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001102When adding object variables one usually doesn't think much about this, just
1103get the type right. And normally the values are set in the new() method.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001104Therefore defaulting to read access only "just works" in most cases. And when
1105directly writing you get an error, which makes you wonder if you actually want
1106to allow that. This helps writing code with fewer mistakes.
1107
1108
Ernie Rael03042a22023-11-11 08:53:32 +01001109Making object variables protected with an underscore ~
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001110
Ernie Rael03042a22023-11-11 08:53:32 +01001111When an object variable is protected, it can only be read and changed inside
1112the class (and in sub-classes), then it cannot be used outside of the class.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001113Prepending an underscore is a simple way to make that visible. Various
1114programming languages have this as a recommendation.
1115
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001116In case you change your mind and want to make the object variable accessible
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001117outside of the class, you will have to remove the underscore everywhere.
1118Since the name only appears in the class (and sub-classes) they will be easy
1119to find and change.
1120
1121The other way around is much harder: you can easily prepend an underscore to
Ernie Rael03042a22023-11-11 08:53:32 +01001122the object variable inside the class to make it protected, but any usage
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001123elsewhere you will have to track down and change. You may have to make it a
1124"set" method call. This reflects the real world problem that taking away
1125access requires work to be done for all places where that access exists.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001126
Ernie Rael03042a22023-11-11 08:53:32 +01001127An alternative would have been using the "protected" keyword, just like
1128"public" changes the access in the other direction. Well, that's just to
1129reduce the number of keywords.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001130
1131
Ernie Rael03042a22023-11-11 08:53:32 +01001132No private object variables ~
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001133
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001134Some languages provide several ways to control access to object variables.
1135The most known is "protected", and the meaning varies from language to
Ernie Rael03042a22023-11-11 08:53:32 +01001136language. Others are "shared", "private", "package" and even "friend".
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001137
1138These rules make life more difficult. That can be justified in projects where
1139many people work on the same, complex code where it is easy to make mistakes.
1140Especially when refactoring or other changes to the class model.
1141
1142The Vim scripts are expected to be used in a plugin, with just one person or a
1143small team working on it. Complex rules then only make it more complicated,
Bram Moolenaar71badf92023-04-22 22:40:14 +01001144the extra safety provided by the rules isn't really needed. Let's just keep
1145it simple and not specify access details.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001146
1147
1148==============================================================================
1149
115010. To be done later
1151
1152Can a newSomething() constructor invoke another constructor? If yes, what are
1153the restrictions?
1154
1155Thoughts:
1156- Generics for a class: `class <Tkey, Tentry>`
1157- Generics for a function: `def <Tkey> GetLast(key: Tkey)`
1158- Mixins: not sure if that is useful, leave out for simplicity.
1159
1160Some things that look like good additions:
1161- For testing: Mock mechanism
1162
1163An important class to be provided is "Promise". Since Vim is single
1164threaded, connecting asynchronous operations is a natural way of allowing
1165plugins to do their work without blocking the user. It's a uniform way to
1166invoke callbacks and handle timeouts and errors.
1167
1168
1169 vim:tw=78:ts=8:noet:ft=help:norl: