blob: 5e5c28e9e378836e569eefbcfd70897fd312f655 [file] [log] [blame]
Yegappan Lakshmanan7e898002025-02-11 22:07:05 +01001*vim9class.txt* For Vim version 9.1. Last change: 2025 Feb 11
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})'
Christian Brabandt6c1afa32024-01-01 20:50:51 +0100107< *E1317* *E1327* *:this*
errael1d4fcfe2023-12-21 08:34:15 -0800108If you have been using other object-oriented languages you will notice that in
Aliaksei Budaveib2149952024-01-07 17:52:10 +0300109Vim, within a class definition, the declared object members are consistently
110referred to with the "this." prefix. This is different from languages like
111Java and TypeScript. The naming convention makes the object members easy to
112spot. Also, when a variable does not have the "this." prefix you know it is
113not an object variable.
errael1d4fcfe2023-12-21 08:34:15 -0800114 *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
Aliaksei Budaveib2149952024-01-07 17:52:10 +0300119 pos.SetCol(10)
errael1d4fcfe2023-12-21 08:34:15 -0800120<
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
Aliaksei Budavei0aed99a2023-12-29 01:08:24 +0300147 public var lnum: number
148 public var 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
Aliaksei Budaveib2149952024-01-07 17:52:10 +0300167 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
Aliaksei Budaveib2149952024-01-07 17:52:10 +0300177 def GetCol(): number
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000178 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*
errael92feeaf2023-12-27 10:07:09 -0800215See also |default-constructor| and |multiple-constructors|.
216
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700217Many constructors take values for the object variables. Thus you very often
218see this pattern: >
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000219
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000220 class SomeClass
Doug Kearns74da0ee2023-12-14 20:26:26 +0100221 var lnum: number
222 var col: number
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000223
224 def new(lnum: number, col: number)
225 this.lnum = lnum
226 this.col = col
227 enddef
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000228 endclass
h-eastdb385522023-09-28 22:18:19 +0200229<
230 *E1390*
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700231Not only is this text you need to write, it also has the type of each
Dominique Pellé17dca3c2023-12-14 20:36:32 +0100232variable twice. Since this is so common a shorter way to write new() is
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700233provided: >
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000234
235 def new(this.lnum, this.col)
236 enddef
237
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700238The semantics are easy to understand: Providing the object variable name,
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000239including "this.", as the argument to new() means the value provided in the
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700240new() call is assigned to that object variable. This mechanism comes from the
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000241Dart language.
242
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700243Putting together this way of using new() and making the variables public
244results in a much shorter class definition than what we started with: >
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000245
246 class TextPosition
Doug Kearns74da0ee2023-12-14 20:26:26 +0100247 public var lnum: number
248 public var col: number
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000249
250 def new(this.lnum, this.col)
251 enddef
252
253 def SetPosition(lnum: number, col: number)
254 this.lnum = lnum
255 this.col = col
256 enddef
257 endclass
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000258
259The sequence of constructing a new object is:
2601. Memory is allocated and cleared. All values are zero/false/empty.
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07002612. For each declared object variable that has an initializer, the expression
262 is evaluated and assigned to the variable. This happens in the sequence
263 the variables are declared in the class.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00002643. Arguments in the new() method in the "this.name" form are assigned.
2654. The body of the new() method is executed.
266
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000267If the class extends a parent class, the same thing happens. In the second
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700268step the object variables of the parent class are initialized first. There is
269no need to call "super()" or "new()" on the parent.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000270
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200271 *E1365*
Yegappan Lakshmanan6ac15442023-08-20 18:20:17 +0200272When defining the new() method the return type should not be specified. It
273always returns an object of the class.
274
Yegappan Lakshmanan7e898002025-02-11 22:07:05 +0100275The new() method can be made a protected method by using "_new()". This can
276be used to support the singleton design pattern.
277
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200278 *E1386*
279When invoking an object method, the method name should be preceded by the
Dominique Pellé17dca3c2023-12-14 20:36:32 +0100280object variable name. An object method cannot be invoked using the class
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200281name.
282
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000283==============================================================================
284
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +02002853. Class Variables and Methods *Vim9-class-member*
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000286
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200287 *:static* *E1337* *E1338* *E1368*
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000288Class members are declared with "static". They are used by the name without a
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200289prefix in the class where they are defined: >
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000290
291 class OtherThing
Doug Kearns74da0ee2023-12-14 20:26:26 +0100292 var size: number
293 static var totalSize: number
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000294
295 def new(this.size)
296 totalSize += this.size
297 enddef
298 endclass
299< *E1340* *E1341*
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700300Since the name is used as-is, shadowing the name by a method argument name
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000301or local variable name is not allowed.
302
Yegappan Lakshmananb90e3bc2023-09-28 23:06:48 +0200303 *E1374* *E1375* *E1384* *E1385*
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200304To access a class member outside of the class where it is defined, the class
305name prefix must be used. A class member cannot be accessed using an object.
306
Ernie Rael03042a22023-11-11 08:53:32 +0100307Just like object members the access can be made protected by using an
308underscore as the first character in the name, and it can be made public by
309prefixing "public": >
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000310
311 class OtherThing
Doug Kearns74da0ee2023-12-14 20:26:26 +0100312 static var total: number # anybody can read, only class can write
313 static var _sum: number # only class can read and write
314 public static var result: number # anybody can read and write
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000315 endclass
316<
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200317 *class-method*
318Class methods are also declared with "static". They can use the class
319variables but they have no access to the object variables, they cannot use the
h_eastba77bbb2023-10-03 04:47:13 +0900320"this" keyword:
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200321>
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000322 class OtherThing
Doug Kearns74da0ee2023-12-14 20:26:26 +0100323 var size: number
324 static var totalSize: number
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000325
326 # Clear the total size and return the value it had before.
327 static def ClearTotalSize(): number
328 var prev = totalSize
329 totalSize = 0
330 return prev
331 enddef
332 endclass
333
Aliaksei Budavei95740222024-04-04 23:05:33 +0300334Inside the class, the class method can be called by name directly, outside the
335class, the class name must be prefixed: `OtherThing.ClearTotalSize()`. Also,
336the name prefix must be used for public class methods in the special contexts
337of class variable initializers and of lambda expressions and nested functions:
338>
339 class OtherThing
340 static var name: string = OtherThing.GiveName()
341
342 static def GiveName(): string
343 def DoGiveName(): string
344 return OtherThing.NameAny()
345 enddef
346
347 return DoGiveName()
348 enddef
349
350 static def NameAny(): string
351 return "any"
352 enddef
353 endclass
354<
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000355
Ernie Rael03042a22023-11-11 08:53:32 +0100356Just like object methods the access can be made protected by using an
357underscore as the first character in the method name: >
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +0200358
359 class OtherThing
360 static def _Foo()
361 echo "Foo"
362 enddef
363 def Bar()
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200364 _Foo()
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +0200365 enddef
366 endclass
Gianmaria Bajo4b9777a2023-08-29 22:26:30 +0200367<
368 *E1370*
Ernie Rael4e286312023-12-24 11:03:31 +0100369Note that constructors cannot be declared as "static". They are called like a
370static but execute as an object method; they have access to "this".
Yegappan Lakshmanancd7293b2023-08-27 19:18:23 +0200371
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200372To access the class methods and class variables of a super class in an
373extended class, the class name prefix should be used just as from anywhere
374outside of the defining class: >
375
376 vim9script
377 class Vehicle
Doug Kearns74da0ee2023-12-14 20:26:26 +0100378 static var nextID: number = 1000
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200379 static def GetID(): number
380 nextID += 1
381 return nextID
382 enddef
383 endclass
384 class Car extends Vehicle
Doug Kearns74da0ee2023-12-14 20:26:26 +0100385 var myID: number
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200386 def new()
387 this.myID = Vehicle.GetID()
388 enddef
389 endclass
390<
391Class variables and methods are not inherited by a child class. A child class
392can declare a static variable or a method with the same name as the one in the
393super class. Depending on the class where the member is used the
394corresponding class member will be used. The type of the class member in a
395child class can be different from that in the super class.
396
Yegappan Lakshmananff6f0d52023-12-21 16:46:18 +0100397The double underscore (__) prefix for a class or object method name is
398reserved for future use.
399
Yegappan Lakshmanane5437c52023-12-16 14:11:19 +0100400 *object-final-variable* *E1409*
401The |:final| keyword can be used to make a class or object variable a
402constant. Examples: >
403
404 class A
405 final v1 = [1, 2] # final object variable
406 public final v2 = {x: 1} # final object variable
407 static final v3 = 'abc' # final class variable
408 public static final v4 = 0z10 # final class variable
409 endclass
410<
411A final variable can be changed only from a constructor function. Example: >
412
413 class A
414 final v1: list<number>
415 def new()
416 this.v1 = [1, 2]
417 enddef
418 endclass
419 var a = A.new()
420 echo a.v1
421<
422Note that the value of a final variable can be changed. Example: >
423
424 class A
425 public final v1 = [1, 2]
426 endclass
427 var a = A.new()
428 a.v1[0] = 6 # OK
429 a.v1->add(3) # OK
430 a.v1 = [3, 4] # Error
431<
432 *E1408*
433Final variables are not supported in an interface. A class or object method
434cannot be final.
435
436 *object-const-variable*
437The |:const| keyword can be used to make a class or object variable and the
438value a constant. Examples: >
439
440 class A
441 const v1 = [1, 2] # const object variable
442 public const v2 = {x: 1} # const object variable
443 static const v3 = 'abc' # const class variable
444 public static const v4 = 0z10 # const class variable
445 endclass
446<
447A const variable can be changed only from a constructor function. Example: >
448
449 class A
450 const v1: list<number>
451 def new()
452 this.v1 = [1, 2]
453 enddef
454 endclass
455 var a = A.new()
456 echo a.v1
457<
458A const variable and its value cannot be changed. Example: >
459
460 class A
461 public const v1 = [1, 2]
462 endclass
463 var a = A.new()
464 a.v1[0] = 6 # Error
465 a.v1->add(3) # Error
466 a.v1 = [3, 4] # Error
467<
468 *E1410*
469Const variables are not supported in an interface. A class or object method
470cannot be a const.
471
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000472==============================================================================
473
4744. Using an abstract class *Vim9-abstract-class*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000475
476An abstract class forms the base for at least one sub-class. In the class
477model one often finds that a few classes have the same properties that can be
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000478shared, but a class with these properties does not have enough state to create
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000479an object from. A sub-class must extend the abstract class and add the
480missing state and/or methods before it can be used to create objects for.
481
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000482For example, a Shape class could store a color and thickness. You cannot
483create a Shape object, it is missing the information about what kind of shape
484it is. The Shape class functions as the base for a Square and a Triangle
485class, for which objects can be created. Example: >
486
487 abstract class Shape
Doug Kearns74da0ee2023-12-14 20:26:26 +0100488 var color = Color.Black
489 var thickness = 10
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000490 endclass
491
492 class Square extends Shape
Doug Kearns74da0ee2023-12-14 20:26:26 +0100493 var size: number
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000494
495 def new(this.size)
496 enddef
497 endclass
498
499 class Triangle extends Shape
Doug Kearns74da0ee2023-12-14 20:26:26 +0100500 var base: number
501 var height: number
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000502
503 def new(this.base, this.height)
504 enddef
505 endclass
506<
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000507An abstract class is defined the same way as a normal class, except that it
508does not have any new() method. *E1359*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000509
h_east596a9f22023-11-21 21:24:23 +0900510 *abstract-method* *E1371* *E1372*
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +0200511An abstract method can be defined in an abstract class by using the "abstract"
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700512prefix when defining the method: >
Yegappan Lakshmanan7bcd25c2023-09-08 19:27:51 +0200513
514 abstract class Shape
515 abstract def Draw()
516 endclass
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200517<
Yegappan Lakshmananef9e3f82023-11-02 20:43:57 +0100518A static method in an abstract class cannot be an abstract method.
519
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200520 *E1373*
Aliaksei Budaveib2149952024-01-07 17:52:10 +0300521A non-abstract class extending the abstract class must implement all the
522abstract methods. The signature (arguments, argument types and return type)
523must be exactly the same. If the return type of a method is a class, then
524that class or one of its subclasses can be used in the extended method.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000525
526==============================================================================
527
Bram Moolenaarbe4e0162023-02-02 13:59:48 +00005285. Using an interface *Vim9-using-interface*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000529
530The example above with Shape, Square and Triangle can be made more useful if
531we add a method to compute the surface of the object. For that we create the
532interface called HasSurface, which specifies one method Surface() that returns
533a number. This example extends the one above: >
534
535 abstract class Shape
Doug Kearns74da0ee2023-12-14 20:26:26 +0100536 var color = Color.Black
537 var thickness = 10
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000538 endclass
539
540 interface HasSurface
541 def Surface(): number
542 endinterface
543
544 class Square extends Shape implements HasSurface
Doug Kearns74da0ee2023-12-14 20:26:26 +0100545 var size: number
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000546
547 def new(this.size)
548 enddef
549
550 def Surface(): number
551 return this.size * this.size
552 enddef
553 endclass
554
555 class Triangle extends Shape implements HasSurface
Doug Kearns74da0ee2023-12-14 20:26:26 +0100556 var base: number
557 var height: number
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000558
559 def new(this.base, this.height)
560 enddef
561
562 def Surface(): number
563 return this.base * this.height / 2
564 enddef
565 endclass
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200566<
567 *E1348* *E1349* *E1367* *E1382* *E1383*
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000568If a class declares to implement an interface, all the items specified in the
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200569interface must appear in the class, with the same types.
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000570
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000571The interface name can be used as a type: >
572
573 var shapes: list<HasSurface> = [
574 Square.new(12),
575 Triangle.new(8, 15),
576 ]
577 for shape in shapes
578 echo $'the surface is {shape.Surface()}'
579 endfor
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200580<
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200581 *E1378* *E1379* *E1380* *E1387*
582An interface can contain only object methods and read-only object variables.
Ernie Rael03042a22023-11-11 08:53:32 +0100583An interface cannot contain read-write or protected object variables,
584protected object methods, class variables and class methods.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000585
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200586An interface can extend another interface using "extends". The sub-interface
587inherits all the instance variables and methods from the super interface.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000588
589==============================================================================
590
Bram Moolenaarbe4e0162023-02-02 13:59:48 +00005916. More class details *Vim9-class* *Class* *class*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000592
593Defining a class ~
594 *:class* *:endclass* *:abstract*
595A class is defined between `:class` and `:endclass`. The whole class is
596defined in one script file. It is not possible to add to a class later.
597
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000598A class can only be defined in a |Vim9| script file. *E1316*
Yegappan Lakshmananc51578f2024-04-13 17:58:09 +0200599A class cannot be defined inside a function. *E1429*
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000600
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000601It is possible to define more than one class in a script file. Although it
602usually is better to export only one main class. It can be useful to define
603types, enums and helper classes though.
604
605The `:abstract` keyword may be prefixed and `:export` may be used. That gives
606these variants: >
607
608 class ClassName
609 endclass
610
611 export class ClassName
612 endclass
613
614 abstract class ClassName
615 endclass
616
617 export abstract class ClassName
618 endclass
619<
620 *E1314*
621The class name should be CamelCased. It must start with an uppercase letter.
622That avoids clashing with builtin types.
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000623 *E1315*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000624After the class name these optional items can be used. Each can appear only
625once. They can appear in any order, although this order is recommended: >
626 extends ClassName
627 implements InterfaceName, OtherInterface
628 specifies SomeInterface
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200629< *E1355* *E1369*
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700630Each variable and method name can be used only once. It is not possible to
631define a method with the same name and different type of arguments. It is not
Aliaksei Budaveib2149952024-01-07 17:52:10 +0300632possible to use a public and protected member variable with the same name. An
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700633object variable name used in a super class cannot be reused in a child class.
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000634
635
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700636Object Variable Initialization ~
Ernie Rael03042a22023-11-11 08:53:32 +0100637
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700638If the type of a variable is not explicitly specified in a class, then it is
639set to "any" during class definition. When an object is instantiated from the
640class, then the type of the variable is set.
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200641
Yegappan Lakshmananf3b68d42023-09-29 22:50:02 +0200642The following reserved keyword names cannot be used as an object or class
643variable name: "super", "this", "true", "false", "null", "null_blob",
644"null_dict", "null_function", "null_list", "null_partial", "null_string",
645"null_channel" and "null_job".
Yegappan Lakshmanan618e47d2023-08-22 21:29:28 +0200646
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000647Extending a class ~
648 *extends*
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000649A class can extend one other class. *E1352* *E1353* *E1354*
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000650The basic idea is to build on top of an existing class, add properties to it.
651
652The extended class is called the "base class" or "super class". The new class
653is called the "child class".
654
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700655Object variables from the base class are all taken over by the child class. It
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000656is not possible to override them (unlike some other languages).
657
658 *E1356* *E1357* *E1358*
Yegappan Lakshmananb32064f2023-10-02 21:43:58 +0200659Object methods of the base class can be overruled. The signature (arguments,
Yegappan Lakshmanan26e8f7b2023-10-06 10:24:10 -0700660argument types and return type) must be exactly the same. If the return type
661of a method is a class, then that class or one of its subclasses can be used
662in the extended method. The method of the base class can be called by
663prefixing "super.".
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000664
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200665 *E1377*
Ernie Rael03042a22023-11-11 08:53:32 +0100666The access level of a method (public or protected) in a child class should be
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200667the same as the super class.
668
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000669Other object methods of the base class are taken over by the child class.
670
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700671Class methods, including methods starting with "new", can be overruled, like
672with object methods. The method on the base class can be called by prefixing
673the name of the class (for class methods) or "super.".
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000674
675Unlike other languages, the constructor of the base class does not need to be
676invoked. In fact, it cannot be invoked. If some initialization from the base
677class also needs to be done in a child class, put it in an object method and
678call that method from every constructor().
679
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700680If the base class did not specify a new() method then one was automatically
681created. This method will not be taken over by the child class. The child
682class can define its own new() method, or, if there isn't one, a new() method
683will be added automatically.
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000684
685
686A class implementing an interface ~
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200687 *implements* *E1346* *E1347* *E1389*
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000688A class can implement one or more interfaces. The "implements" keyword can
689only appear once *E1350* . Multiple interfaces can be specified, separated by
690commas. Each interface name can appear only once. *E1351*
Bram Moolenaarbe4e0162023-02-02 13:59:48 +0000691
692
693A class defining an interface ~
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000694 *specifies*
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700695A class can declare its interface, the object variables and methods, with a
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000696named interface. This avoids the need for separately specifying the
Bram Moolenaar00b28d62022-12-08 15:32:33 +0000697interface, which is often done in many languages, especially Java.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000698
699
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000700Items in a class ~
Yegappan Lakshmanan2dede3d2023-09-27 19:02:01 +0200701 *E1318* *E1325* *E1388*
Bram Moolenaardd60c362023-02-27 15:49:53 +0000702Inside a class, in between `:class` and `:endclass`, these items can appear:
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700703- An object variable declaration: >
Doug Kearns74da0ee2023-12-14 20:26:26 +0100704 var _protectedVariableName: memberType
705 var readonlyVariableName: memberType
706 public var readwriteVariableName: memberType
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700707- A class variable declaration: >
Doug Kearns74da0ee2023-12-14 20:26:26 +0100708 static var _protectedClassVariableName: memberType
709 static var readonlyClassVariableName: memberType
Aliaksei Budaveib2149952024-01-07 17:52:10 +0300710 public static var readwriteClassVariableName: memberType
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000711- A constructor method: >
Bram Moolenaar938ae282023-02-20 20:44:55 +0000712 def new(arguments)
713 def newName(arguments)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200714- A class method: >
715 static def SomeMethod(arguments)
Ernie Rael03042a22023-11-11 08:53:32 +0100716 static def _ProtectedMethod(arguments)
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000717- An object method: >
Bram Moolenaar938ae282023-02-20 20:44:55 +0000718 def SomeMethod(arguments)
Ernie Rael03042a22023-11-11 08:53:32 +0100719 def _ProtectedMethod(arguments)
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200720
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700721For the object variable the type must be specified. The best way is to do
722this explicitly with ": {type}". For simple types you can also use an
723initializer, such as "= 123", and Vim will see that the type is a number.
724Avoid doing this for more complex types and when the type will be incomplete.
725For example: >
Doug Kearns74da0ee2023-12-14 20:26:26 +0100726 var nameList = []
Bram Moolenaarf1dcd142022-12-31 15:30:45 +0000727This specifies a list, but the item type is unknown. Better use: >
Doug Kearns74da0ee2023-12-14 20:26:26 +0100728 var nameList: list<string>
Bram Moolenaarf1dcd142022-12-31 15:30:45 +0000729The initialization isn't needed, the list is empty by default.
730 *E1330*
731Some types cannot be used, such as "void", "null" and "v:none".
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000732
Yegappan Lakshmanand3eae7b2024-03-03 16:26:58 +0100733Builtin Object Methods ~
734 *builtin-object-methods*
735Some of the builtin functions like |empty()|, |len()| and |string()| can be
736used with an object. An object can implement a method with the same name as
737these builtin functions to return an object-specific value.
738
739 *E1412*
740The following builtin methods are supported:
741 *object-empty()*
742 empty() Invoked by the |empty()| function to check whether an object is
743 empty. If this method is missing, then true is returned. This
744 method should not accept any arguments and must return a boolean.
745 *object-len()*
746 len() Invoked by the |len()| function to return the length of an
747 object. If this method is missing in the class, then an error is
748 given and zero is returned. This method should not accept any
749 arguments and must return a number.
750 *object-string()*
751 string() Invoked by the |string()| function to get a textual
752 representation of an object. Also used by the |:echo| command
753 for an object. If this method is missing in the class, then a
754 built-in default textual representation is used. This method
755 should not accept any arguments and must return a string.
756
757 *E1413*
758A class method cannot be used as a builtin method.
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000759
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000760Defining an interface ~
Christian Brabandt6c1afa32024-01-01 20:50:51 +0100761 *Interface* *:interface* *:endinterface*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000762An interface is defined between `:interface` and `:endinterface`. It may be
763prefixed with `:export`: >
764
765 interface InterfaceName
766 endinterface
767
768 export interface InterfaceName
769 endinterface
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000770< *E1344*
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700771An interface can declare object variables, just like in a class but without
772any initializer.
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000773 *E1345*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000774An interface can declare methods with `:def`, including the arguments and
775return type, but without the body and without `:enddef`. Example: >
776
777 interface HasSurface
Doug Kearns74da0ee2023-12-14 20:26:26 +0100778 var size: number
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000779 def Surface(): number
780 endinterface
781
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000782An interface name must start with an uppercase letter. *E1343*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000783The "Has" prefix can be used to make it easier to guess this is an interface
784name, with a hint about what it provides.
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000785An interface can only be defined in a |Vim9| script file. *E1342*
Yegappan Lakshmanan00cd1822023-09-18 19:56:49 +0200786An interface cannot "implement" another interface but it can "extend" another
787interface. *E1381*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000788
789
Bram Moolenaar938ae282023-02-20 20:44:55 +0000790null object ~
791
Bram Moolenaardd60c362023-02-27 15:49:53 +0000792When a variable is declared to have the type of an object, but it is not
Bram Moolenaar938ae282023-02-20 20:44:55 +0000793initialized, the value is null. When trying to use this null object Vim often
794does not know what class was supposed to be used. Vim then cannot check if
Aliaksei Budaveib2149952024-01-07 17:52:10 +0300795a variable name is correct and you will get a "Using a null object" error,
h_eastba77bbb2023-10-03 04:47:13 +0900796even when the variable name is invalid. *E1360* *E1362*
Bram Moolenaar938ae282023-02-20 20:44:55 +0000797
798
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000799Default constructor ~
Yegappan Lakshmanan413f8392023-09-28 22:46:37 +0200800 *default-constructor*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000801In case you define a class without a new() method, one will be automatically
802defined. This default constructor will have arguments for all the object
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700803variables, in the order they were specified. Thus if your class looks like: >
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000804
805 class AutoNew
Doug Kearns74da0ee2023-12-14 20:26:26 +0100806 var name: string
807 var age: number
808 var gender: Gender
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000809 endclass
810
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700811Then the default constructor will be: >
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000812
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000813 def new(this.name = v:none, this.age = v:none, this.gender = v:none)
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000814 enddef
815
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000816The "= v:none" default values make the arguments optional. Thus you can also
817call `new()` without any arguments. No assignment will happen and the default
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700818value for the object variables will be used. This is a more useful example,
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000819with default values: >
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000820
821 class TextPosition
Doug Kearns74da0ee2023-12-14 20:26:26 +0100822 var lnum: number = 1
823 var col: number = 1
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000824 endclass
825
826If you want the constructor to have mandatory arguments, you need to write it
827yourself. For example, if for the AutoNew class above you insist on getting
828the name, you can define the constructor like this: >
829
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000830 def new(this.name, this.age = v:none, this.gender = v:none)
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000831 enddef
Yegappan Lakshmanan563e6442023-12-05 08:19:06 -0800832<
833When using the default new() method, if the order of the object variables in
834the class is changed later, then all the callers of the default new() method
Aliaksei Budaveib2149952024-01-07 17:52:10 +0300835need to change. To avoid this, the new() method can be explicitly defined
Yegappan Lakshmanan563e6442023-12-05 08:19:06 -0800836without any arguments.
837
838 *E1328*
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000839Note that you cannot use another default value than "v:none" here. If you
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700840want to initialize the object variables, do it where they are declared. This
Bram Moolenaar65b0d162022-12-13 18:43:22 +0000841way you only need to look in one place for the default values.
Bram Moolenaar7db29e42022-12-11 15:53:04 +0000842
Ernie Rael03042a22023-11-11 08:53:32 +0100843All object variables will be used in the default constructor, including
844protected access ones.
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000845
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -0700846If the class extends another one, the object variables of that class will come
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +0000847first.
848
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000849
850Multiple constructors ~
errael92feeaf2023-12-27 10:07:09 -0800851 *multiple-constructors*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000852Normally a class has just one new() constructor. In case you find that the
853constructor is often called with the same arguments you may want to simplify
854your code by putting those arguments into a second constructor method. For
855example, if you tend to use the color black a lot: >
856
857 def new(this.garment, this.color, this.size)
858 enddef
859 ...
860 var pants = new(Garment.pants, Color.black, "XL")
861 var shirt = new(Garment.shirt, Color.black, "XL")
862 var shoes = new(Garment.shoes, Color.black, "45")
863
864Instead of repeating the color every time you can add a constructor that
865includes it: >
866
867 def newBlack(this.garment, this.size)
868 this.color = Color.black
869 enddef
870 ...
871 var pants = newBlack(Garment.pants, "XL")
872 var shirt = newBlack(Garment.shirt, "XL")
873 var shoes = newBlack(Garment.shoes, "9.5")
874
875Note that the method name must start with "new". If there is no method called
876"new()" then the default constructor is added, even though there are other
877constructor methods.
878
Yegappan Lakshmanan56d45f12024-11-11 19:58:55 +0100879Using variable type "any" for an Object~
880 *obj-var-type-any*
881You can use a variable declared with type "any" to hold an object. e.g.
882>
883 vim9script
884 class A
885 var n = 10
886 def Get(): number
887 return this.n
888 enddef
889 endclass
890
891 def Fn(o: any)
892 echo o.n
893 echo o.Get()
894 enddef
895
896 var a = A.new()
897 Fn(a)
898<
899In this example, Vim cannot determine the type of the parameter "o" for
900function Fn() at compile time. It can be either a |Dict| or an |Object|
901value. Therefore, at runtime, when the type is known, the object member
902variable and method are looked up. This process is not efficient, so it is
903recommended to use a more specific type whenever possible for better
904efficiency.
905
Yegappan Lakshmanan4f32c832024-01-12 17:36:40 +0100906Compiling methods in a Class ~
907 *class-compile*
908The |:defcompile| command can be used to compile all the class and object
909methods defined in a class: >
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000910
Yegappan Lakshmanan4f32c832024-01-12 17:36:40 +0100911 defcompile MyClass # Compile class "MyClass"
912 defcompile # Compile the classes in the current script
913<
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000914==============================================================================
915
Christian Brabandt6c1afa32024-01-01 20:50:51 +01009167. Type definition *typealias* *Vim9-type* *:type*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000917
Yegappan Lakshmanan2a71b542023-12-14 20:03:03 +0100918 *E1393* *E1395* *E1396* *E1397* *E1398*
919A type definition is giving a name to a type specification. This is also
920known as a "type alias". The type alias can be used wherever a built-in type
921can be used. Example: >
Yegappan Lakshmanan26e8f7b2023-10-06 10:24:10 -0700922
Yegappan Lakshmanan2a71b542023-12-14 20:03:03 +0100923 type ListOfStrings = list<string>
924 var s: ListOfStrings = ['a', 'b']
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000925
Yegappan Lakshmanan2a71b542023-12-14 20:03:03 +0100926 def ProcessStr(str: ListOfStrings): ListOfStrings
927 return str
928 enddef
929 echo ProcessStr(s)
930<
931 *E1394*
932A type alias name must start with an upper case character. Only existing
933types can be aliased.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000934
Yegappan Lakshmanan2a71b542023-12-14 20:03:03 +0100935 *E1399*
936A type alias can be created only at the script level and not inside a
937function. A type alias can be exported and used across scripts.
938
939 *E1400* *E1401* *E1402* *E1403* *E1407*
940A type alias cannot be used as an expression. A type alias cannot be used in
941the left-hand-side of an assignment.
942
943For a type alias name, the |typename()| function returns the type that is
944aliased: >
945
946 type ListOfStudents = list<dict<any>>
947 echo typename(ListOfStudents)
948 typealias<list<dict<any>>>
949<
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000950==============================================================================
951
Bram Moolenaarbe4e0162023-02-02 13:59:48 +00009528. Enum *Vim9-enum* *:enum* *:endenum*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000953
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +0100954 *enum* *E1418* *E1419* *E1420*
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000955An enum is a type that can have one of a list of values. Example: >
956
Doug Kearns49a35f62024-12-29 15:33:12 +0100957 enum Color
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +0100958 White,
959 Red,
960 Green, Blue, Black
Doug Kearns49a35f62024-12-29 15:33:12 +0100961 endenum
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +0100962<
963 *enumvalue* *E1422*
964The enum values are separated by commas. More than one enum value can be
965listed in a single line. The final enum value should not be followed by a
966comma.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000967
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +0100968An enum value is accessed using the enum name followed by the value name: >
Bram Moolenaarc1c365c2022-12-04 20:13:24 +0000969
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +0100970 var a: Color = Color.Blue
971<
972Enums are treated as classes, where each enum value is essentially an instance
973of that class. Unlike typical object instantiation with the |new()| method,
974enum instances cannot be created this way.
975
976An enum can only be defined in a |Vim9| script file. *E1414*
977An enum cannot be defined inside a function.
978
979 *E1415*
980An enum name must start with an uppercase letter. The name of an enum value
981in an enum can start with an upper or lowercase letter.
982
983 *E1416*
984An enum can implement an interface but cannot extend a class: >
985
986 enum MyEnum implements MyIntf
987 Value1,
988 Value2
989
990 def SomeMethod()
991 enddef
992 endenum
993<
994 *enum-constructor*
995The enum value objects in an enum are constructed like any other objects using
996the |new()| method. Arguments can be passed to the enum constructor by
997specifying them after the enum value name, just like calling a function. The
998default constructor doesn't have any arguments.
999
1000 *E1417*
1001An enum can contain class variables, class methods, object variables and
1002object methods. The methods in an enum cannot be |:abstract| methods.
1003
1004The following example shows an enum with object variables and methods: >
1005
1006 vim9script
1007 enum Planet
1008 Earth(1, false),
1009 Jupiter(95, true),
1010 Saturn(146, true)
1011
1012 var moons: number
1013 var has_rings: bool
1014 def GetMoons(): number
1015 return this.moons
1016 enddef
1017 endenum
1018 echo Planet.Jupiter.GetMoons()
1019 echo Planet.Earth.has_rings
1020<
1021 *E1421* *E1423* *E1424* *E1425*
Aliaksei Budavei95740222024-04-04 23:05:33 +03001022Enums and their values are immutable. They cannot be utilized as numerical or
1023string types. Enum values can declare mutable instance variables.
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +01001024
1025 *enum-name*
1026Each enum value object has a "name" instance variable which contains the name
1027of the enum value. This is a readonly variable.
1028
1029 *enum-ordinal* *E1426*
1030Each enum value has an associated ordinal number starting with 0. The ordinal
1031number of an enum value can be accessed using the "ordinal" instance variable.
1032This is a readonly variable. Note that if the ordering of the enum values in
1033an enum is changed, then their ordinal values will also change.
1034
1035 *enum-values*
1036All the values in an enum can be accessed using the "values" class variable
1037which is a List of the enum objects. This is a readonly variable.
1038
1039Example: >
1040 enum Planet
1041 Mercury,
1042 Venus,
1043 Earth
1044 endenum
1045
1046 echo Planet.Mercury
1047 echo Planet.Venus.name
1048 echo Planet.Venus.ordinal
1049 for p in Planet.values
1050 # ...
1051 endfor
1052<
1053An enum is a class with class variables for the enum value objects and object
1054variables for the enum value name and the enum value ordinal: >
1055
1056 enum Planet
1057 Mercury,
1058 Venus
1059 endenum
1060<
1061The above enum definition is equivalent to the following class definition: >
1062
1063 class Planet
1064 public static final Mercury: Planet = Planet.new('Mercury', 0)
1065 public static final Venus: Planet = Planet.new('Venus', 1)
1066
1067 public static const values: list<Planet> = [Planet.Mercury, Planet.Venus]
1068
1069 public const name: string
1070 public const ordinal: number
1071 endclass
1072<
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001073==============================================================================
1074
10759. Rationale
1076
1077Most of the choices for |Vim9| classes come from popular and recently
1078developed languages, such as Java, TypeScript and Dart. The syntax has been
1079made to fit with the way Vim script works, such as using `endclass` instead of
1080using curly braces around the whole class.
1081
1082Some common constructs of object-oriented languages were chosen very long ago
1083when this kind of programming was still new, and later found to be
1084sub-optimal. By this time those constructs were widely used and changing them
1085was not an option. In Vim we do have the freedom to make different choices,
1086since classes are completely new. We can make the syntax simpler and more
1087consistent than what "old" languages use. Without diverting too much, it
1088should still mostly look like what you know from existing languages.
1089
1090Some recently developed languages add all kinds of fancy features that we
1091don't need for Vim. But some have nice ideas that we do want to use.
1092Thus we end up with a base of what is common in popular languages, dropping
1093what looks like a bad idea, and adding some nice features that are easy to
1094understand.
1095
1096The main rules we use to make decisions:
1097- Keep it simple.
1098- No surprises, mostly do what other languages are doing.
1099- Avoid mistakes from the past.
1100- Avoid the need for the script writer to consult the help to understand how
1101 things work, most things should be obvious.
1102- Keep it consistent.
1103- Aim at an average size plugin, not at a huge project.
1104
1105
1106Using new() for the constructor ~
1107
1108Many languages use the class name for the constructor method. A disadvantage
1109is that quite often this is a long name. And when changing the class name all
1110constructor methods need to be renamed. Not a big deal, but still a
1111disadvantage.
1112
1113Other languages, such as TypeScript, use a specific name, such as
1114"constructor()". That seems better. However, using "new" or "new()" to
1115create a new object has no obvious relation with "constructor()".
1116
1117For |Vim9| script using the same method name for all constructors seemed like
1118the right choice, and by calling it new() the relation between the caller and
1119the method being called is obvious.
1120
1121
1122No overloading of the constructor ~
1123
1124In Vim script, both legacy and |Vim9| script, there is no overloading of
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001125methods. That means it is not possible to use the same method name with
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001126different types of arguments. Therefore there also is only one new()
1127constructor.
1128
1129With |Vim9| script it would be possible to support overloading, since
1130arguments are typed. However, this gets complicated very quickly. Looking at
1131a new() call one has to inspect the types of the arguments to know which of
1132several new() methods is actually being called. And that can require
1133inspecting quite a bit of code. For example, if one of the arguments is the
1134return value of a method, you need to find that method to see what type it is
1135returning.
1136
1137Instead, every constructor has to have a different name, starting with "new".
1138That way multiple constructors with different arguments are possible, while it
1139is very easy to see which constructor is being used. And the type of
1140arguments can be properly checked.
1141
1142
1143No overloading of methods ~
1144
1145Same reasoning as for the constructor: It is often not obvious what type
1146arguments have, which would make it difficult to figure out what method is
1147actually being called. Better just give the methods a different name, then
1148type checking will make sure it works as you intended. This rules out
1149polymorphism, which we don't really need anyway.
1150
1151
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +00001152Single inheritance and interfaces ~
1153
1154Some languages support multiple inheritance. Although that can be useful in
1155some cases, it makes the rules of how a class works quite complicated.
1156Instead, using interfaces to declare what is supported is much simpler. The
1157very popular Java language does it this way, and it should be good enough for
Bram Moolenaarbe4e0162023-02-02 13:59:48 +00001158Vim. The "keep it simple" rule applies here.
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +00001159
1160Explicitly declaring that a class supports an interface makes it easy to see
1161what a class is intended for. It also makes it possible to do proper type
1162checking. When an interface is changed any class that declares to implement
1163it will be checked if that change was also changed. The mechanism to assume a
1164class implements an interface just because the methods happen to match is
1165brittle and leads to obscure problems, let's not do that.
1166
1167
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001168Using "this.variable" everywhere ~
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001169
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001170The object variables in various programming languages can often be accessed in
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001171different ways, depending on the location. Sometimes "this." has to be
1172prepended to avoid ambiguity. They are usually declared without "this.".
1173That is quite inconsistent and sometimes confusing.
1174
1175A very common issue is that in the constructor the arguments use the same name
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001176as the object variable. Then for these variables "this." needs to be prefixed
1177in the body, while for other variables this is not needed and often omitted.
1178This leads to a mix of variables with and without "this.", which is
1179inconsistent.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001180
Aliaksei Budaveib2149952024-01-07 17:52:10 +03001181For |Vim9| classes the "this." prefix is always used for declared methods and
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001182variables. Simple and consistent. When looking at the code inside a class
1183it's also directly clear which variable references are object variables and
1184which aren't.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001185
1186
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001187Using class variables ~
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001188
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001189Using "static variable" to declare a class variable is very common, nothing
1190new here. In |Vim9| script these can be accessed directly by their name.
1191Very much like how a script-local variable can be used in a method. Since
1192object variables are always accessed with "this." prepended, it's also quickly
1193clear what kind of variable it is.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001194
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001195TypeScript prepends the class name before the class variable name, also inside
1196the class. This has two problems: The class name can be rather long, taking
1197up quite a bit of space, and when the class is renamed all these places need
1198to be changed too.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001199
1200
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001201Declaring object and class variables ~
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +00001202
1203The main choice is whether to use "var" as with variable declarations.
1204TypeScript does not use it: >
1205 class Point {
1206 x: number;
1207 y = 0;
1208 }
1209
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001210Following that Vim object variables could be declared like this: >
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +00001211 class Point
1212 this.x: number
1213 this.y = 0
1214 endclass
1215
1216Some users pointed out that this looks more like an assignment than a
Aliaksei Budaveib2149952024-01-07 17:52:10 +03001217declaration. Adding "var" and omitting "this." changes that: >
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +00001218 class Point
Doug Kearns74da0ee2023-12-14 20:26:26 +01001219 var x: number
1220 var y = 0
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +00001221 endclass
1222
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001223We also need to be able to declare class variables using the "static" keyword.
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +00001224There we can also choose to leave out "var": >
1225 class Point
Doug Kearns74da0ee2023-12-14 20:26:26 +01001226 var x: number
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +00001227 static count = 0
1228 endclass
1229
1230Or do use it, before "static": >
1231 class Point
Doug Kearns74da0ee2023-12-14 20:26:26 +01001232 var x: number
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +00001233 var static count = 0
1234 endclass
1235
1236Or after "static": >
1237 class Point
Doug Kearns74da0ee2023-12-14 20:26:26 +01001238 var x: number
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +00001239 static var count = 0
1240 endclass
1241
1242This is more in line with "static def Func()".
1243
1244There is no clear preference whether to use "var" or not. The two main
1245reasons to leave it out are:
Doug Kearns74da0ee2023-12-14 20:26:26 +010012461. TypeScript and other popular languages do not use it.
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +000012472. Less clutter.
1248
Doug Kearns74da0ee2023-12-14 20:26:26 +01001249However, it is more common for languages to reuse their general variable and
1250function declaration syntax for class/object variables and methods. Vim9 also
1251reuses the general function declaration syntax for methods. So, for the sake
1252of consistency, we require "var" in these declarations.
1253
Bram Moolenaar1b5f03e2023-01-09 20:12:45 +00001254
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001255Using "ClassName.new()" to construct an object ~
1256
1257Many languages use the "new" operator to create an object, which is actually
1258kind of strange, since the constructor is defined as a method with arguments,
1259not a command. TypeScript also has the "new" keyword, but the method is
1260called "constructor()", it is hard to see the relation between the two.
1261
1262In |Vim9| script the constructor method is called new(), and it is invoked as
1263new(), simple and straightforward. Other languages use "new ClassName()",
1264while there is no ClassName() method, it's a method by another name in the
1265class called ClassName. Quite confusing.
1266
1267
Ernie Rael03042a22023-11-11 08:53:32 +01001268Vim9class access modes ~
1269 *vim9-access-modes*
1270The variable access modes, and their meaning, supported by Vim9class are
1271 |public-variable| read and write from anywhere
1272 |read-only-variable| read from anywhere, write from inside the
1273 class and sub-classes
1274 |protected-variable| read and write from inside the class and
1275 sub-classes
1276
1277The method access modes are similar, but without the read-only mode.
1278
1279
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001280Default read access to object variables ~
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001281
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001282Some users will remark that the access rules for object variables are
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001283asymmetric. Well, that is intentional. Changing a value is a very different
1284action than reading a value. The read operation has no side effects, it can
1285be done any number of times without affecting the object. Changing the value
1286can have many side effects, and even have a ripple effect, affecting other
1287objects.
1288
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001289When adding object variables one usually doesn't think much about this, just
1290get the type right. And normally the values are set in the new() method.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001291Therefore defaulting to read access only "just works" in most cases. And when
1292directly writing you get an error, which makes you wonder if you actually want
1293to allow that. This helps writing code with fewer mistakes.
1294
1295
Ernie Rael03042a22023-11-11 08:53:32 +01001296Making object variables protected with an underscore ~
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001297
Ernie Rael03042a22023-11-11 08:53:32 +01001298When an object variable is protected, it can only be read and changed inside
1299the class (and in sub-classes), then it cannot be used outside of the class.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001300Prepending an underscore is a simple way to make that visible. Various
1301programming languages have this as a recommendation.
1302
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001303In case you change your mind and want to make the object variable accessible
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001304outside of the class, you will have to remove the underscore everywhere.
1305Since the name only appears in the class (and sub-classes) they will be easy
1306to find and change.
1307
1308The other way around is much harder: you can easily prepend an underscore to
Ernie Rael03042a22023-11-11 08:53:32 +01001309the object variable inside the class to make it protected, but any usage
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001310elsewhere you will have to track down and change. You may have to make it a
1311"set" method call. This reflects the real world problem that taking away
1312access requires work to be done for all places where that access exists.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001313
Ernie Rael03042a22023-11-11 08:53:32 +01001314An alternative would have been using the "protected" keyword, just like
1315"public" changes the access in the other direction. Well, that's just to
1316reduce the number of keywords.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001317
1318
Ernie Rael03042a22023-11-11 08:53:32 +01001319No private object variables ~
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001320
Yegappan Lakshmananc3b315f2023-09-24 14:36:17 -07001321Some languages provide several ways to control access to object variables.
1322The most known is "protected", and the meaning varies from language to
Ernie Rael03042a22023-11-11 08:53:32 +01001323language. Others are "shared", "private", "package" and even "friend".
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001324
1325These rules make life more difficult. That can be justified in projects where
1326many people work on the same, complex code where it is easy to make mistakes.
1327Especially when refactoring or other changes to the class model.
1328
1329The Vim scripts are expected to be used in a plugin, with just one person or a
1330small team working on it. Complex rules then only make it more complicated,
Bram Moolenaar71badf92023-04-22 22:40:14 +01001331the extra safety provided by the rules isn't really needed. Let's just keep
1332it simple and not specify access details.
Bram Moolenaarc1c365c2022-12-04 20:13:24 +00001333
1334
1335==============================================================================
1336
133710. To be done later
1338
1339Can a newSomething() constructor invoke another constructor? If yes, what are
1340the restrictions?
1341
1342Thoughts:
1343- Generics for a class: `class <Tkey, Tentry>`
1344- Generics for a function: `def <Tkey> GetLast(key: Tkey)`
1345- Mixins: not sure if that is useful, leave out for simplicity.
1346
1347Some things that look like good additions:
1348- For testing: Mock mechanism
1349
1350An important class to be provided is "Promise". Since Vim is single
1351threaded, connecting asynchronous operations is a natural way of allowing
1352plugins to do their work without blocking the user. It's a uniform way to
1353invoke callbacks and handle timeouts and errors.
1354
1355
1356 vim:tw=78:ts=8:noet:ft=help:norl: