vim9class.txt ForVim version 9.2. Last change: 2026 Feb 14VIM REFERENCE MANUAL by Bram MoolenaarVim9 classes, objects, interfaces, types and enums.vim9-class1. OverviewVim9-class-overview2.A simpleclassVim9-simple-class3.Classvariables and methodsVim9-class-member4. Using an abstractclassVim9-abstract-class5. Using aninterfaceVim9-using-interface6. Moreclass detailsVim9-class7. Type definitionVim9-type8. EnumVim9-enum9. Rationale10. To be done later==============================================================================1. OverviewVim9-class-overviewThe fancy termis "object-oriented programming". You can find lots of studymaterial on this subject. Here we document whatVim9script provides,assuming you know the basics already. Added are helpful hints about how touse this functionality effectively.Vim9 classes andobjects cannot be usedin legacy Vim scripts and legacy functions.The basic itemis an object:- Anobject stores state. It contains one or morevariables that can each havea value.- Anobject providesfunctions that use and manipulate its state. Thesefunctions are invoked "on theobject", whichis what setsit apart from the traditional separation of data and code that manipulates the data.- Anobject hasa well defined interface, with typed membervariables and methods.- Objects are created fromaclass and allobjects have the same interface. This does not changeat runtime,itis not dynamic.Anobject can only be created bya class.Aclass provides:-Anew() method, the constructor, which returns anobject for the class. Thismethodis invoked on theclass name: MyClass.new().- State shared by allobjects of the class:classvariables (class members).-A hierarchy of classes, with super-classes and sub-classes, inheritance.Aninterfaceis used to specify properties of an object:- Anobject can declare several interfaces thatit implements.- Differentobjects implementing the sameinterface can be used the same way.Theclass hierarchy allows for single inheritance. Otherwise interfaces areto be used where needed.Class modelingYou can model classes any way you like. Keep in mind what you are building,don't try to model the real world. This can be confusing, especially becauseteachers use real-worldobjects to explainclass relations and you might thinkyour model should therefore reflect the real world. It doesn't! The modelshould match your purpose.Keep in mind that composition (anobject contains other objects)is oftenbetter than inheritance (anobjectextends another object). Don't waste timetrying to find the optimalclass model. Or waste time discussing whetherasquareisa rectangle or thata rectangleisa square. It doesn't matter.==============================================================================2.A simpleclassVim9-simple-classLet's start witha simple example:aclass that storesa text position (seebelow for how todo this more efficiently):class TextPosition var lnum: number var col: number def new(lnum: number, col: number) this.lnum = lnum this.col = col enddef def SetLnum(lnum: number) this.lnum = lnum enddef def SetCol(col: number) this.col = col enddef def SetPosition(lnum: number, col: number) this.lnum = lnum this.col = col enddef endclassobjectObjectYou can create anobject from thisclass with thenew() method:var pos = TextPosition.new(1, 1)Theobjectvariables "lnum" and "col" can be accessed directly:echo $'The text position is ({pos.lnum}, {pos.col})'E1317E1327:thisIf you have been using other object-oriented languages you will notice that inVim, withinaclass definition, the declaredobject members are consistentlyreferred to with the "this." prefix. Thisis different from languages likeJava and TypeScript. The naming convention makes theobject memberseasy tospot. Also, whena variable does not have the "this." prefix you knowitisnot anobject variable.E1411From outside theclass definition, access an object's methods andvariables byusing theobject name followed bya dot following by the member:pos.lnumpos.SetCol(10)E1405E1406Aclass name cannot be usedas an expression.Aclass name cannot be used inthe left-hand-side of an assignment.Object variable write accessread-only-variableNow try to change anobject variable directly:pos.lnum = 9E1335This will give you an error! Thatis because by defaultobjectvariables canbe read but not set. That's why the TextPositionclass providesamethod forit:pos.SetLnum(9)Allowing to read but not set anobject variableis the most common and safestway. Most often thereis no problem usinga value, while settinga value mayhave side effects that need to be taken care of. In this case, the SetLnum()method could check if the line numberis valid and either give an error or usethe closest valid value.:publicpublic-variableE1331If you don't care about side effects and want to allow theobject variable tobe changedat any time, you can makeit public:public var lnum: numberpublic var col: numberNow you don't need the SetLnum(), SetCol() and SetPosition() methods, setting"pos.lnum" directly above will no longer give an error.E1326If you try to set anobject variable that doesn't exist you get an error:pos.other = 9E1326: Member not found on object "TextPosition": otherE1376Aobject variable cannot be accessed using theclass name.Protected variablesprotected-variableE1332E1333On the other hand, if youdo not want theobjectvariables to be read directlyfrom outside theclass or its sub-classes, you can make them protected. Thisis done by prefixing an underscore to the name:var _lnum: numbervar _col: numberNow you need to provide methods to get the value of the protected variables.These are commonly called getters. We recommend usinga name that starts with"Get":def GetLnum(): number return this._lnumenddefdef GetCol(): number return this._colenddefThis example isn't very useful, thevariables mightas well have been public.It does become useful if you check the value. For example, restrict the linenumber to the total number of lines:def GetLnum(): number if this._lnum > this._lineCount return this._lineCount endif return this._lnumenddefProtected methodsprotected-methodE1366If you wantobject methods to be accessible only from other methods of thesameclass and not used from outside the class, then you can make themprotected. Thisis done by prefixing themethod name with an underscore: class SomeClassdef _Foo(): number return 10enddefdef Bar(): number return this._Foo()enddef endclassAccessinga protectedmethod outside theclass will result in an error (usingthe above class): var a = SomeClass.new() a._Foo()Simplifying the new() methodnew()constructorSee alsodefault-constructor andmultiple-constructors.Many constructors take values for theobject variables. Thus you very oftensee this pattern: class SomeClass var lnum: number var col: number def new(lnum: number, col: number) this.lnum = lnum this.col = col enddef endclassE1390Not onlyis this text you need to write,it also has the type of eachvariable twice. Since thisis so commona shorter way to writenew()isprovided: def new(this.lnum, this.col) enddefThe semantics areeasy to understand: Providing theobject variable name,including "this.",as the argument tonew() means the value provided in thenew() callis assigned to thatobject variable. This mechanism comes from theDart language.Putting together this way of usingnew() and making thevariables publicresults ina much shorterclass definition than what we started with:class TextPosition public var lnum: number public var col: number def new(this.lnum, this.col) enddef def SetPosition(lnum: number, col: number) this.lnum = lnum this.col = col enddef endclassThe sequence of constructinga newobject is:1. Memoryis allocated and cleared. All values are zero/false/empty.2. For each declaredobject variable that has an initializer, theexpressionis evaluated and assigned to the variable. This happens in the sequence thevariables are declared in the class.3. Arguments in thenew()method in the "this.name" form are assigned.4. The body of thenew()methodis executed.If theclassextendsa parent class, the same thing happens. In the secondstep theobjectvariables of the parentclass are initialized first. Thereisno need to call "super()" or "new()" on the parent.E1365When defining thenew()method the return type should not be specified. Italways returns anobject of the class.Thenew()method can be madea protectedmethod by using "_new()". This canbe used to support the singleton design pattern.E1386When invoking anobject method, themethod name should be preceded by theobject variable name. Anobjectmethod cannot be invoked using theclassname.==============================================================================3.Class Variables and MethodsVim9-class-member:staticE1329E1337E1338E1368Class members are declared with "static". They are used by the name withoutaprefix in theclass where they are defined:class OtherThing var size: number static var totalSize: number def new(this.size) totalSize += this.size enddefendclassE1340E1341Since the nameis used as-is, shadowing the name byamethod argument nameor local variable nameis not allowed.E1374E1375E1384E1385To accessaclass member outside of theclass whereitis defined, theclassname prefixmust be used.Aclass member cannot be accessed using an object.Just likeobject members the access can be made protected by using anunderscoreas the first character in the name, andit can be made public byprefixing "public": class OtherThingstatic var total: number # anybody can read, only class can writestatic var _sum: number # only class can read and writepublic static var result: number # anybody can read and write endclassclass-methodClass methods are also declared with "static". They can use theclassvariables but they have no access to theobject variables, they cannot use the"this" keyword:class OtherThing var size: number static var totalSize: number # Clear the total size and return the value it had before. static def ClearTotalSize(): number var prev = totalSize totalSize = 0 return prev enddefendclassInside the class, theclassmethod can be called by name directly, outside theclass, theclass namemust be prefixed:OtherThing.ClearTotalSize(). Also,the name prefixmust be used for publicclass methods in the special contextsofclass variable initializers and oflambda expressions and nested functions: class OtherThingstatic var name: string = OtherThing.GiveName()static def GiveName(): string def DoGiveName(): stringreturn OtherThing.NameAny() enddef return DoGiveName()enddefstatic def NameAny(): string return "any"enddef endclassJust likeobject methods the access can be made protected by using anunderscoreas the first character in themethod name: class OtherThingstatic def _Foo() echo "Foo"enddefdef Bar() _Foo()enddef endclassE1370Note that constructors cannot be declaredas "static". They are called likeastatic but executeas anobject method; they have access to "this".To access theclass methods andclassvariables ofa superclass in anextended class, theclass name prefix should be used justas from anywhereoutside of the defining class: vim9script class Vehiclestatic var nextID: number = 1000static def GetID(): number nextID += 1 return nextIDenddef endclass class Car extends Vehiclevar myID: numberdef new() this.myID = Vehicle.GetID()enddef endclassClassvariables and methods are not inherited bya child class.A childclasscan declarea static variable oramethod with the same nameas the one in thesuper class. Depending on theclass where the memberis used thecorrespondingclass member will be used. The type of theclass member inachildclass can be different from that in the super class.The double underscore (__) prefix foraclass orobjectmethod nameisreserved for future use.object-final-variableE1409The:final keyword can be used to makeaclass orobject variableaconstant. Examples: class Afinal v1 = [1, 2]# final object variablepublic final v2 = {x: 1}# final object variablestatic final v3 = 'abc'# final class variablepublic static final v4 = 0z10# final class variable endclassA final variable can be changed only fromaconstructor function. Example: class Afinal v1: list<number>def new() this.v1 = [1, 2]enddef endclass var a = A.new() echo a.v1Note that the value ofa final variable can be changed. Example: class Apublic final v1 = [1, 2] endclass var a = A.new() a.v1[0] = 6# OK a.v1->add(3)# OK a.v1 = [3, 4]# ErrorE1408Finalvariables are not supported in an interface.Aclass orobjectmethodcannot be final.object-const-variableThe:const keyword can be used to makeaclass orobject variable and thevaluea constant. Examples: class Aconst v1 = [1, 2]# const object variablepublic const v2 = {x: 1}# const object variablestatic const v3 = 'abc'# const class variablepublic static const v4 = 0z10# const class variable endclassA const variable can be changed only fromaconstructor function. Example: class Aconst v1: list<number>def new() this.v1 = [1, 2]enddef endclass var a = A.new() echo a.v1A const variable and its value cannot be changed. Example: class Apublic const v1 = [1, 2] endclass var a = A.new() a.v1[0] = 6# Error a.v1->add(3)# Error a.v1 = [3, 4]# ErrorE1410Constvariables are not supported in an interface.Aclass orobjectmethodcannot bea const.==============================================================================4. Using an abstractclassVim9-abstract-classAn abstractclass forms the base forat least one sub-class. In theclassmodel one often finds thata few classes have the same properties that can beshared, butaclass with these properties does not have enough state to createanobject from.A sub-classmust extend the abstractclass and add themissing state and/or methods beforeit can be used to createobjects for.For example,a Shapeclass could storea color and thickness. You cannotcreatea Shape object,itis missing the information about what kind of shapeit is. The Shapeclassfunctionsas the base fora Square anda Triangleclass, for whichobjects can be created. Example:abstract class Shape var color = Color.Black var thickness = 10endclassclass Square extends Shape var size: number def new(this.size) enddefendclassclass Triangle extends Shape var base: number var height: number def new(this.base, this.height) enddefendclassAn abstractclassis defined the same wayasa normal class, except thatitdoes not have anynew() method.E1359abstract-methodE1371E1372An abstractmethod can be defined in an abstractclass by using the "abstract"prefix when defining the method:abstract class Shape abstract def Draw()endclassA staticmethod in an abstractclass cannot be an abstract method.E1404Aninterfacemethod cannot be an abstract method.E1373A non-abstractclass extending the abstractclassmust implement all theabstract methods. The signature (arguments, argument types and return type)must be exactly the same. If the return type ofamethodisa class, thenthatclass or one of its subclasses can be used in the extended method.E1431An abstractmethod in an abstract superclass cannot be invoked.==============================================================================5. Using aninterfaceVim9-using-interfaceThe example above with Shape, Square and Triangle can be made more useful ifwe addamethod to compute the surface of the object. For that we create theinterface called HasSurface, whichspecifies onemethod Surface() that returnsa number. This exampleextends the one above:abstract class Shape var color = Color.Black var thickness = 10endclassinterface HasSurface def Surface(): numberendinterfaceclass Square extends Shape implements HasSurface var size: number def new(this.size) enddef def Surface(): number return this.size * this.size enddefendclassclass Triangle extends Shape implements HasSurface var base: number var height: number def new(this.base, this.height) enddef def Surface(): number return this.base * this.height / 2 enddefendclassE1348E1349E1367E1382E1383Ifaclass declares to implement an interface, all the items specified in theinterfacemust appear in the class, with the same types.Theinterface name can be usedasa type:var shapes: list<HasSurface> = [Square.new(12),Triangle.new(8, 15),]for shape in shapes echo $'the surface is {shape.Surface()}'endforE1378E1379E1380E1387Aninterface can contain onlyobject methods and read-onlyobject variables.Aninterface cannot contain read-write or protectedobject variables,protectedobject methods,classvariables andclass methods.Aninterface can extend anotherinterface using "extends". The sub-interfaceinherits all the instancevariables and methods from the super interface.Aninterface cannot be defined insidea function.E1436==============================================================================6. Moreclass detailsVim9-classClassclassDefining a class:class:endclass:abstractAclassis defined between:class and:endclass. The wholeclassisdefined in onescript file. Itis not possible to add toaclass later.Aclass can only be defined inaVim9script file.E1316Aclass cannot be defined insidea function.E1429Itis possible to define more than oneclass inascript file. Althoughitusuallyis better to export only one main class. It can be useful to definetypes, enums and helper classes though.The:abstract keyword may be prefixed and:export may be used. That givesthese variants:class ClassNameendclassexport class ClassNameendclassabstract class ClassNameendclassexport abstract class ClassNameendclassE1314Theclass name should be CamelCased. Itmust start with anuppercase letter.That avoids clashing with builtin types.E1315After theclass name these optional items can be used. Each can appear onlyonce. They can appear in any order, although this orderis recommended:extends ClassNameimplements InterfaceName, OtherInterfacespecifies SomeInterfaceThe "specifies" featureis currently not implemented.E1355E1369Each variable andmethod name can be used only once. Itis not possible todefineamethod with the same name and different type of arguments. Itis notpossible to usea public and protected member variable with the same name. Anobject variable name used ina superclass cannot be reused ina child class.Object Variable InitializationE1430If the type ofa variableis not explicitly specified ina class, thenitisset to "any" duringclass definition. When anobjectis instantiated from theclass, then the type of the variableis set.The following reserved keyword names cannot be usedas anobject orclassvariable name: "super", "this", "true", "false", "null", "null_blob","null_channel", "null_class", "null_dict", "null_function", "null_job","null_list", "null_object", "null_partial" and "null_string".Extending a classextendsAclass can extend one other class.E1352E1353E1354The basic ideais to build on top of an existing class, add properties to it.The extendedclassis called the "baseclass" or "superclass". The newclassis called the "childclass".Objectvariables from the baseclass are all taken over by the child class.Itis not possible to override them (unlike some other languages).E1356E1357E1358Object methods of the baseclass can be overruled. The signature (arguments,argument types and return type)must be exactly the same. If the return typeofamethodisa class, then thatclass or one of its subclasses can be usedin the extended method. Themethod of the baseclass can be called byprefixing "super.".E1377The access level ofamethod (public or protected) ina childclass should bethe sameas the super class.Otherobject methods of the baseclass are taken over by the child class.Class methods, including methodsstarting with "new", can be overruled, likewithobject methods. Themethod on the baseclass can be called by prefixingthe name of theclass (forclass methods) or "super.".Unlike other languages, theconstructor of the baseclass does not need to beinvoked. In fact,it cannot be invoked. If someinitialization from the baseclass also needs to be done ina child class,putit in anobjectmethod andcall thatmethod from every constructor().If the baseclass did not specifyanew()method then one was automaticallycreated. Thismethod will not be taken over by the child class. The childclass can define its ownnew() method, or, if there isn't one,anew()methodwill be added automatically.A class implementing an interfaceimplementsE1346E1347E1389Aclass can implement one or more interfaces. The "implements" keyword canonly appear onceE1350. Multiple interfaces can be specified, separated bycommas. Eachinterface name can appear only once.E1351A class defining an interfacespecifiesAclass can declare its interface, theobjectvariables and methods, withanamed interface. This avoids the need for separately specifying theinterface, whichis often done in many languages, especially Java.TODO: Thisis currently not implemented.Items in a classE1318E1325E1388Insidea class, in between:class and:endclass, these items can appear:- Anobject variable declaration:var _protectedVariableName: memberTypevar readonlyVariableName: memberTypepublic var readwriteVariableName: memberType-Aclass variable declaration:static var _protectedClassVariableName: memberTypestatic var readonlyClassVariableName: memberTypepublic static var readwriteClassVariableName: memberType-Aconstructor method:def new(arguments)def newName(arguments)-Aclass method:static def SomeMethod(arguments)static def _ProtectedMethod(arguments)- Anobject method:def SomeMethod(arguments)def _ProtectedMethod(arguments)For theobject variable the typemust be specified. The best wayis todothis explicitly with ":{type}". For simple types you can also use aninitializer, suchas "= 123", and Vim will see that the typeisa number.Avoid doing this for more complex types and when the type will be incomplete.For example:var nameList = []Thisspecifiesa list, but the item typeis unknown. Better use:var nameList: list<string>Theinitialization isn't needed, thelistis empty by default.E1330Some types cannot be used, suchas "void", "null" and "v:none".Builtin Object Methodsbuiltin-object-methodsSome of the builtinfunctions likeempty(),len() andstring() can beused with an object. Anobject can implementamethod with the same nameasthese builtinfunctions to return an object-specific value.E1412The following builtin methods are supported:object-empty()empty() Invoked by theempty() function to check whether anobjectis empty. If thismethodis missing, thentrueis returned. Thismethod should not accept any arguments andmust returna boolean.object-len()len() Invoked by thelen() function to return the length of an object. If thismethodis missing in the class, then an erroris given and zerois returned. Thismethod should not accept any arguments andmust returna number.object-string()string() Invoked by thestring() function to geta textual representation of an object. Also used by the:echo command for an object. If thismethodis missing in the class, thena built-in default textual representationis used. Thismethod should not accept any arguments andmust returna string.E1413Aclassmethod cannot be usedasa builtin method.Defining an interfaceinterfaceInterface:interface:endinterfaceAninterfaceis defined between:interface and:endinterface. It may beprefixed with:export:interface InterfaceNameendinterfaceexport interface InterfaceNameendinterfaceE1344Aninterface can declareobject variables, just like inaclass but withoutany initializer.E1345Aninterface can declare methods with:def, including the arguments andreturn type, but without the body and without:enddef. Example:interface HasSurface var size: number def Surface(): numberendinterfaceAninterface namemust start with anuppercase letter.E1343The "Has" prefix can be used to makeit easier to guess thisis aninterfacename, witha hint about whatit provides.Aninterface can only be defined inaVim9script file.E1342Aninterface cannot "implement" anotherinterface butit can "extend" anotherinterface.E1381null objectWhena variableis declared to have the type of an object, butitis notinitialized, the valueis null. When trying to use thisnullobject Vim oftendoes not know whatclass was supposed to be used. Vim then cannot check ifa variable nameis correct and you will geta "Usinganullobject" error,even when the variable nameis invalid.E1360E1362Default constructordefault-constructorIncase you defineaclass withoutanew() method, one will be automaticallydefined. This defaultconstructor will have arguments for all theobjectvariables, in the order they were specified. Thus if yourclass looks like:class AutoNew var name: string var age: number var gender: GenderendclassThen the defaultconstructor will be:def new(this.name = v:none, this.age = v:none, this.gender = v:none)enddefThe "=v:none" default values make the arguments optional. Thus you can alsocallnew() without any arguments. No assignment will happen and the defaultvalue for theobjectvariables will be used. Thisisa more useful example,with default values:class TextPosition var lnum: number = 1 var col: number = 1endclassIf you want theconstructor to have mandatory arguments, you need to writeityourself. For example, if for the AutoNewclass above you insist on gettingthe name, you can define theconstructor like this:def new(this.name, this.age = v:none, this.gender = v:none)enddefWhen using the defaultnew() method, if the order of theobjectvariables intheclassis changed later, then all the callers of the defaultnew()methodneed to change. To avoid this, thenew()method can be explicitly definedwithout any arguments.E1328Note that you cannot use another default value than "v:none" here. If youwant to initialize theobject variables,doit where they are declared. Thisway you only need to look in one place for the default values.Allobjectvariables will be used in the default constructor, includingprotected access ones.If theclassextends another one, theobjectvariables of thatclass will comefirst.Multiple constructorsmultiple-constructorsNormallyaclass has just onenew() constructor. Incase you find that theconstructoris often called with the same arguments you may want to simplifyyour code by putting those arguments intoa secondconstructor method. Forexample, if you tend to use the color blacka lot:def new(this.garment, this.color, this.size)enddef...var pants = new(Garment.pants, Color.black, "XL")var shirt = new(Garment.shirt, Color.black, "XL")var shoes = new(Garment.shoes, Color.black, "45")Instead ofrepeating the color every time you can addaconstructor thatincludes it:def newBlack(this.garment, this.size) this.color = Color.blackenddef...var pants = newBlack(Garment.pants, "XL")var shirt = newBlack(Garment.shirt, "XL")var shoes = newBlack(Garment.shoes, "9.5")Note that themethod namemust start with "new". If thereis nomethod called"new()" then the defaultconstructoris added, even though there are otherconstructor methods.Using variable type "any" for an Objectobj-var-type-anyYou can usea variable declared with type "any" to hold an object. e.g. vim9script class Avar n = 10def Get(): number return this.nenddef endclass def Fn(o: any)echo o.necho o.Get() enddef var a = A.new() Fn(a)In this example, Vim cannot determine the type of the parameter "o" forfunction Fn()at compile time. It can be eitheraDict or anObjectvalue. Therefore,at runtime, when the typeis known, theobject membervariable andmethod are looked up. This processis not efficient, soitisrecommended to usea more specific type whenever possible for betterefficiency.Compiling methods in a Classclass-compileThe:defcompile command can be used to compile all theclass andobjectmethods defined ina class:defcompile MyClass# Compile class "MyClass"defcompile# Compile the classes in the current script==============================================================================7. Type definitiontypealiasVim9-type:typeE1393E1395E1396E1397E1398A type definitionis givinga name toa type specification. Thisis alsoknownasa "type alias". The type alias can be used wherevera built-in typecan be used. Example: type ListOfStrings = list<string> var s: ListOfStrings = ['a', 'b'] def ProcessStr(str: ListOfStrings): ListOfStringsreturn str enddef echo ProcessStr(s)E1394A type alias namemust start with an uppercase character. Only existingtypes can be aliased.E1399A type alias can be created onlyat thescript level and not insideafunction.A type alias can be exported and used across scripts.E1400E1401E1402E1403E1407A type alias cannot be usedas an expression.A type alias cannot be used inthe left-hand-side of an assignment.Fora type alias name, thetypename() function returns the type thatisaliased: type ListOfStudents = list<dict<any>> echo typename(ListOfStudents) typealias<list<dict<any>>>==============================================================================8. EnumVim9-enum:enum:endenumenumE1418E1419E1420Anenumisa type that can have one ofalist of values. Example: enum ColorWhite,Red,Green, Blue, Black endenumenumvalueE1422E1428Theenum values are separated by commas. More than oneenum value can belisted ina single line. The finalenum value should not be followed byacomma. Duplicateenum values are not allowed.Anenum valueis accessed using theenum name followed by the value name: var a: Color = Color.BlueEnums are treatedas classes, where eachenum valueis essentially an instanceof that class. Unlike typicalobject instantiation with thenew() method,enum instances cannot be created this way.Anenum can only be defined inaVim9script file.E1414Anenum cannot be defined insidea function.E1435E1415Anenum namemust start with anuppercase letter. The name of anenum valuein anenum can start with an upper orlowercase letter.E1416Anenum can implement aninterface but cannot extenda class: enum MyEnum implements MyIntfValue1,Value2def SomeMethod()enddef endenumenum-constructorTheenum valueobjects in anenum are constructed like any otherobjects usingthenew() method. Arguments can be passed to theenumconstructor byspecifying them after theenum value name, just like callinga function. Thedefaultconstructor doesn't have any arguments.E1417Anenum can containclass variables,class methods,objectvariables andobject methods. The methods in anenum cannot be:abstract methods.The following example shows anenum withobjectvariables and methods: vim9script enum PlanetEarth(1, false),Jupiter(95, true),Saturn(146, true)var moons: numbervar has_rings: booldef GetMoons(): number return this.moonsenddef endenum echo Planet.Jupiter.GetMoons() echo Planet.Earth.has_ringsE1421E1423E1424E1425Enums and their values are immutable. They cannot be utilizedas numerical orstring types. Enum values can declare mutable instance variables.enum-nameE1427Eachenum valueobject hasa "name" instance variable which contains the nameof theenum value. Thisisa readonly variable.enum-ordinalE1426Eachenum value has an associated ordinal numberstarting with 0. The ordinalnumber of anenum value can be accessed using the "ordinal" instance variable.Thisisa readonly variable.Note that if the ordering of theenum values inanenumis changed, then their ordinal values will also change.enum-valuesAll the values in anenum can be accessed using the "values"class variablewhichisaList of theenum objects. Thisisa readonly variable.Example: enum PlanetMercury,Venus,Earth endenum echo Planet.Mercury echo Planet.Venus.name echo Planet.Venus.ordinal for p in Planet.values# ... endforAnenumisaclass withclassvariables for theenum valueobjects andobjectvariables for theenum value name and theenum value ordinal: enum PlanetMercury,Venus endenumThe aboveenum definitionis equivalent to the followingclass definition: class Planet public static final Mercury: Planet = Planet.new('Mercury', 0) public static final Venus: Planet = Planet.new('Venus', 1) public static const values: list<Planet> = [Planet.Mercury, Planet.Venus] public const name: string public const ordinal: number endclassAenum can containobjectvariables and methods just likea regular class: enum ColorCyan([0, 255, 255]),Magenta([255, 0, 255]),Gray([128, 128, 128])var rgb_values: list<number>def Get_RGB(): list<number> return this.rgb_valuesenddef endenum echo Color.Magenta.Get_RGB()==============================================================================9. RationaleMost of the choices forVim9 classes come from popular and recentlydeveloped languages, suchas Java, TypeScript and Dart. Thesyntax has beenmade to fit with the way Vimscript works, suchas usingendclass instead ofusing curly braces around the whole class.Some common constructs of object-oriented languages were chosen very long agowhen this kind of programming was still new, and later found to besub-optimal. By this time those constructs were widely used andchanging themwas not an option. In Vim wedo have the freedom to make different choices,since classes are completely new. We can make thesyntax simpler and moreconsistent than what "old" languages use. Without diverting too much,itshould still mostly look like what you know from existing languages.Some recently developed languages add all kinds of fancy features that wedon't need for Vim. But some have nice ideas that wedo want to use.Thus weend up witha base of whatis common in popular languages, droppingwhat looks likea bad idea, and adding some nice features that areeasy tounderstand.The main rules we use to make decisions:- Keepit simple.- No surprises, mostlydo what other languages are doing.- Avoid mistakes from the past.- Avoid the need for thescript writer to consult thehelp to understand how things work, most things should be obvious.- Keepit consistent.- Aimat an average size plugin, notata huge project.Using new() for the constructorMany languages use theclass name for theconstructor method.A disadvantageis that quite often thisisa long name. And whenchanging theclass name allconstructor methods need to be renamed. Nota big deal, but stilladisadvantage.Other languages, suchas TypeScript, usea specific name, suchas"constructor()". That seems better. However, using "new" or "new()" tocreatea newobject has no obvious relation with "constructor()".ForVim9script using the samemethod name for all constructors seemed likethe right choice, and by callingitnew() the relation between the caller andthemethod being calledis obvious.No overloading of the constructorIn Vim script, both legacy andVim9 script, thereis no overloading ofmethods. That meansitis not possible to use the samemethod name withdifferent types of arguments. Therefore there alsois only onenew()constructor.WithVim9scriptit would be possible to support overloading, sincearguments are typed. However, this gets complicated very quickly. Lookingatanew() call one has to inspect the types of the arguments to know which ofseveralnew() methodsis actually being called. And that can requireinspecting quitea bit of code. For example, if one of the argumentsis thereturn value ofa method, you need to find thatmethod to see what typeitisreturning.Instead, everyconstructor has to havea different name,starting with "new".That way multiple constructors with different arguments are possible, whileitis veryeasy to see whichconstructoris being used. And the type ofarguments can be properly checked.No overloading of methodsSame reasoningas for the constructor: Itis often not obvious what typearguments have, which would makeit difficult to figure out whatmethodisactually being called. Better just give the methodsa different name, thentype checking will make sureit worksas you intended. This rules outpolymorphism, which we don't really need anyway.Single inheritance and interfacesSome languages support multiple inheritance. Although that can be useful insome cases,it makes the rules of howaclass works quite complicated.Instead, using interfaces to declare whatis supportedis much simpler. Thevery popular Java language doesit this way, andit should be good enough forVim. The "keepit simple" rule applies here.Explicitly declaring thataclass supports aninterface makesiteasy to seewhataclassis intended for. It also makesit possible todo proper typechecking. When aninterfaceis changed anyclass that declares to implementit will be checked if that change was also changed. The mechanism to assumeaclassimplements aninterface just because the methods happen to matchisbrittle and leads to obscure problems, let's notdo that.Using "this.variable" everywhereTheobjectvariables invarious programming languages can often be accessed indifferent ways, depending on the location. Sometimes "this." has to beprepended to avoid ambiguity. They are usually declared without "this.".Thatis quite inconsistent and sometimes confusing.A very common issueis that in theconstructor the arguments use the same nameas theobject variable. Then for thesevariables "this." needs to be prefixedin the body, while for othervariables thisis not needed and often omitted.This leads toa mix ofvariables with and without "this.", whichisinconsistent.ForVim9 classes the "this." prefixis always used for declared methods andvariables. Simple and consistent. When lookingat the code insideaclassit's also directly clear which variable references areobjectvariables andwhich aren't.Using class variablesUsing "static variable" to declareaclass variableis very common, nothingnew here. InVim9script these can be accessed directly by their name.Very much like howascript-local variable can be used ina method. Sinceobjectvariables are always accessed with "this." prepended, it's also quicklyclear what kind of variableit is.TypeScript prepends theclass name before theclass variable name, also insidethe class. This has two problems: Theclass name can be rather long, takingup quitea bit of space, and when theclassis renamed all these places needto be changed too.Declaring object and class variablesThe main choiceis whether to use "var"as with variable declarations.TypeScript does not use it:class Point { x: number; y = 0;}Following that Vimobjectvariables could be declared like this:class Point this.x: number this.y = 0endclassSome users pointed out that this looks more like an assignment thanadeclaration. Adding "var" and omitting "this." changes that:class Point var x: number var y = 0endclassWe also need to be able to declareclassvariables using the "static" keyword.There we can also choose to leave out "var":class Point var x: number static count = 0endclassOrdo use it, before "static":class Point var x: number var static count = 0endclassOr after "static":class Point var x: number static var count = 0endclassThisis more in line with "static def Func()".Thereis no clear preference whether to use "var" or not. The two mainreasons to leaveit out are:1. TypeScript and other popular languagesdo not use it.2. Less clutter.However,itis more common for languages to reuse their general variable andfunction declarationsyntax for class/objectvariables and methods.Vim9 alsoreuses the general function declarationsyntax for methods. So, for the sakeof consistency, we require "var" in these declarations.Using "ClassName.new()" to construct an objectMany languages use the "new"operator to create an object, whichis actuallykind of strange, since theconstructoris definedasamethod with arguments,nota command. TypeScript also has the "new" keyword, but themethodiscalled "constructor()",itis hard to see the relation between the two.InVim9script theconstructormethodis called new(), anditis invokedasnew(), simple and straightforward. Other languages use "new ClassName()",while thereis no ClassName() method, it'samethod by another name in theclass called ClassName. Quite confusing.Vim9class access modesvim9-access-modesThe variable access modes, and their meaning, supported by Vim9class arepublic-variable read and write from anywhereread-only-variable read from anywhere, write from inside theclass and sub-classesprotected-variable read and write from inside theclass andsub-classesThemethod access modes are similar, but without the read-only mode.Default read access to object variablesSome users will remark that the access rules forobjectvariables areasymmetric. Well, thatis intentional. Changinga valueisa very differentaction than readinga value. The read operation has no side effects,it canbe done any number of times without affecting the object. Changing the valuecan have many side effects, and even havea ripple effect, affecting otherobjects.When addingobjectvariables one usually doesn't think much about this, justget the type right. And normally the values are set in thenew() method.Therefore defaulting to read access only "just works" in most cases. And whendirectlywriting you get an error, which makes you wonder if you actually wantto allow that. This helpswriting code with fewer mistakes.Making object variables protected with an underscoreWhen anobject variableis protected,it can only be read and changed insidetheclass (and in sub-classes), thenit cannot be used outside of the class.Prepending an underscoreisa simple way to make that visible. Variousprogramming languages have thisasa recommendation.Incase you change your mind and want to make theobject variable accessibleoutside of the class, you will have to remove the underscore everywhere.Since the name only appears in theclass (and sub-classes) they will beeasyto find and change.The other way aroundis much harder: you can easily prepend an underscore totheobject variable inside theclass to makeit protected, but any usageelsewhere you will have to track down and change. You may have to makeita"set"method call. This reflects the real world problem that taking awayaccess requires work to be done for all places where that access exists.An alternative would have been using the "protected" keyword, just like"public" changes the access in the other direction. Well, that's just toreduce the number of keywords.No private object variablesSome languages provide several ways tocontrol access toobject variables.The most knownis "protected", and the meaning varies from language tolanguage. Others are "shared", "private", "package" and even "friend".These rules make life more difficult. That can be justified in projects wheremany people work on the same, complex code whereitiseasy to make mistakes.Especially when refactoring or other changes to theclass model.The Vim scripts are expected to be used ina plugin, with just one person orasmall team working on it. Complex rules then only makeit more complicated,the extra safety provided by the rules isn't really needed. Let's just keepit simple and not specify access details.==============================================================================10. To be done laterCana newSomething()constructor invoke another constructor? If yes, what arethe restrictions?Thoughts:- Generics fora class: `class <Tkey, Tentry>`- Generics fora function: `def<Tkey> GetLast(key: Tkey)`- Mixins: not sure if thatis useful, leave out for simplicity.Some things that look like good additions:- For testing: Mock mechanismAn importantclass to be providedis "Promise". Since Vimis singlethreaded, connecting asynchronous operationsisa natural way of allowingplugins todo their work without blocking the user. It'sa uniform way toinvoke callbacks and handle timeouts and errors. vim:tw=78:ts=8:noet:ft=help:norl: