summaryrefslogtreecommitdiffstats
path: root/runtime/doc/vim9class.txt
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/doc/vim9class.txt')
-rw-r--r--runtime/doc/vim9class.txt1170
1 files changed, 1170 insertions, 0 deletions
diff --git a/runtime/doc/vim9class.txt b/runtime/doc/vim9class.txt
new file mode 100644
index 0000000..6e94e84
--- /dev/null
+++ b/runtime/doc/vim9class.txt
@@ -0,0 +1,1170 @@
+*vim9class.txt* For Vim version 9.1. Last change: 2024 Jan 06
+
+
+ VIM REFERENCE MANUAL by Bram Moolenaar
+
+
+Vim9 classes, objects, interfaces, types and enums. *vim9-class*
+
+1. Overview |Vim9-class-overview|
+2. A simple class |Vim9-simple-class|
+3. Class variables and methods |Vim9-class-member|
+4. Using an abstract class |Vim9-abstract-class|
+5. Using an interface |Vim9-using-interface|
+6. More class details |Vim9-class|
+7. Type definition |Vim9-type|
+8. Enum |Vim9-enum|
+
+9. Rationale
+10. To be done later
+
+==============================================================================
+
+1. Overview *Vim9-class-overview*
+
+The fancy term is "object-oriented programming". You can find lots of study
+material on this subject. Here we document what |Vim9| script provides,
+assuming you know the basics already. Added are helpful hints about how to
+use this functionality effectively. Vim9 classes and objects cannot be used
+in legacy Vim scripts and legacy functions.
+
+The basic item is an object:
+- An object stores state. It contains one or more variables that can each
+ have a value.
+- An object provides functions that use and manipulate its state. These
+ functions are invoked "on the object", which is what sets it apart from the
+ traditional separation of data and code that manipulates the data.
+- An object has a well defined interface, with typed member variables and
+ methods.
+- Objects are created from a class and all objects have the same interface.
+ This does not change at runtime, it is not dynamic.
+
+An object can only be created by a class. A class provides:
+- A new() method, the constructor, which returns an object for the class.
+ This method is invoked on the class name: MyClass.new().
+- State shared by all objects of the class: class variables (class members).
+- A hierarchy of classes, with super-classes and sub-classes, inheritance.
+
+An interface is used to specify properties of an object:
+- An object can declare several interfaces that it implements.
+- Different objects implementing the same interface can be used the same way.
+
+The class hierarchy allows for single inheritance. Otherwise interfaces are
+to be used where needed.
+
+
+Class modeling ~
+
+You 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 because
+teachers use real-world objects to explain class relations and you might think
+your model should therefore reflect the real world. It doesn't! The model
+should match your purpose.
+
+Keep in mind that composition (an object contains other objects) is often
+better than inheritance (an object extends another object). Don't waste time
+trying to find the optimal class model. Or waste time discussing whether a
+square is a rectangle or that a rectangle is a square. It doesn't matter.
+
+
+==============================================================================
+
+2. A simple class *Vim9-simple-class*
+
+Let's start with a simple example: a class that stores a text position (see
+below for how to do 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
+ endclass
+< *object* *Object*
+You can create an object from this class with the new() method: >
+
+ var pos = TextPosition.new(1, 1)
+<
+The object variables "lnum" and "col" can be accessed directly: >
+
+ echo $'The text position is ({pos.lnum}, {pos.col})'
+< *E1317* *E1327* *:this*
+If you have been using other object-oriented languages you will notice that in
+Vim, within a class definition, the declared object members are consistently
+referred to with the "this." prefix. This is different from languages like
+Java and TypeScript. The naming convention makes the object members easy to
+spot. Also, when a variable does not have the "this." prefix you know it is
+not an object variable.
+ *E1411*
+From outside the class definition, access an object's methods and variables by
+using the object name followed by a dot following by the member: >
+
+ pos.lnum
+ pos.SetCol(10)
+<
+ *E1405* *E1406*
+A class name cannot be used as an expression. A class name cannot be used in
+the left-hand-side of an assignment.
+
+
+Object variable write access ~
+ *read-only-variable*
+Now try to change an object variable directly: >
+
+ pos.lnum = 9
+< *E1335*
+This will give you an error! That is because by default object variables can
+be read but not set. That's why the TextPosition class provides a method for
+it: >
+
+ pos.SetLnum(9)
+
+Allowing to read but not set an object variable is the most common and safest
+way. Most often there is no problem using a value, while setting a value may
+have side effects that need to be taken care of. In this case, the SetLnum()
+method could check if the line number is valid and either give an error or use
+the closest valid value.
+ *:public* *public-variable* *E1331*
+If you don't care about side effects and want to allow the object variable to
+be changed at any time, you can make it public: >
+
+ public var lnum: number
+ public var col: number
+
+Now you don't need the SetLnum(), SetCol() and SetPosition() methods, setting
+"pos.lnum" directly above will no longer give an error.
+ *E1326*
+If you try to set an object variable that doesn't exist you get an error: >
+ pos.other = 9
+< E1326: Member not found on object "TextPosition": other ~
+
+ *E1376*
+A object variable cannot be accessed using the class name.
+
+Protected variables ~
+ *protected-variable* *E1332* *E1333*
+On the other hand, if you do not want the object variables to be read directly
+from outside the class or its sub-classes, you can make them protected. This
+is done by prefixing an underscore to the name: >
+
+ var _lnum: number
+ var _col: number
+
+Now you need to provide methods to get the value of the protected variables.
+These are commonly called getters. We recommend using a name that starts with
+"Get": >
+
+ def GetLnum(): number
+ return this._lnum
+ enddef
+
+ def GetCol(): number
+ return this._col
+ enddef
+
+This example isn't very useful, the variables might as well have been public.
+It does become useful if you check the value. For example, restrict the line
+number to the total number of lines: >
+
+ def GetLnum(): number
+ if this._lnum > this._lineCount
+ return this._lineCount
+ endif
+ return this._lnum
+ enddef
+<
+Protected methods ~
+ *protected-method* *E1366*
+If you want object methods to be accessible only from other methods of the
+same class and not used from outside the class, then you can make them
+protected. This is done by prefixing the method name with an underscore: >
+
+ class SomeClass
+ def _Foo(): number
+ return 10
+ enddef
+ def Bar(): number
+ return this._Foo()
+ enddef
+ endclass
+<
+Accessing a protected method outside the class will result in an error (using
+the above class): >
+
+ var a = SomeClass.new()
+ a._Foo()
+<
+Simplifying the new() method ~
+ *new()* *constructor*
+See also |default-constructor| and |multiple-constructors|.
+
+Many constructors take values for the object variables. Thus you very often
+see this pattern: >
+
+ class SomeClass
+ var lnum: number
+ var col: number
+
+ def new(lnum: number, col: number)
+ this.lnum = lnum
+ this.col = col
+ enddef
+ endclass
+<
+ *E1390*
+Not only is this text you need to write, it also has the type of each
+variable twice. Since this is so common a shorter way to write new() is
+provided: >
+
+ def new(this.lnum, this.col)
+ enddef
+
+The semantics are easy to understand: Providing the object variable name,
+including "this.", as the argument to new() means the value provided in the
+new() call is assigned to that object variable. This mechanism comes from the
+Dart language.
+
+Putting together this way of using new() and making the variables public
+results in a much shorter class 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
+ endclass
+
+The sequence of constructing a new object is:
+1. Memory is allocated and cleared. All values are zero/false/empty.
+2. For each declared object variable that has an initializer, the expression
+ is evaluated and assigned to the variable. This happens in the sequence
+ the variables are declared in the class.
+3. Arguments in the new() method in the "this.name" form are assigned.
+4. The body of the new() method is executed.
+
+If the class extends a parent class, the same thing happens. In the second
+step the object variables of the parent class are initialized first. There is
+no need to call "super()" or "new()" on the parent.
+
+ *E1365*
+When defining the new() method the return type should not be specified. It
+always returns an object of the class.
+
+ *E1386*
+When invoking an object method, the method name should be preceded by the
+object variable name. An object method cannot be invoked using the class
+name.
+
+==============================================================================
+
+3. Class Variables and Methods *Vim9-class-member*
+
+ *:static* *E1337* *E1338* *E1368*
+Class members are declared with "static". They are used by the name without a
+prefix in the class where they are defined: >
+
+ class OtherThing
+ var size: number
+ static var totalSize: number
+
+ def new(this.size)
+ totalSize += this.size
+ enddef
+ endclass
+< *E1340* *E1341*
+Since the name is used as-is, shadowing the name by a method argument name
+or local variable name is not allowed.
+
+ *E1374* *E1375* *E1384* *E1385*
+To access a class member outside of the class where it is defined, the class
+name prefix must be used. A class member cannot be accessed using an object.
+
+Just like object members the access can be made protected by using an
+underscore as the first character in the name, and it can be made public by
+prefixing "public": >
+
+ class OtherThing
+ static var total: number # anybody can read, only class can write
+ static var _sum: number # only class can read and write
+ public static var result: number # anybody can read and write
+ endclass
+<
+ *class-method*
+Class methods are also declared with "static". They can use the class
+variables but they have no access to the object 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
+ enddef
+ endclass
+
+Inside the class the class method can be called by name directly, outside the
+class the class name must be prefixed: `OtherThing.ClearTotalSize()`. To use
+a class method from a parent class in a child class, the class name must be
+prefixed.
+
+Just like object methods the access can be made protected by using an
+underscore as the first character in the method name: >
+
+ class OtherThing
+ static def _Foo()
+ echo "Foo"
+ enddef
+ def Bar()
+ _Foo()
+ enddef
+ endclass
+<
+ *E1370*
+Note that constructors cannot be declared as "static". They are called like a
+static but execute as an object method; they have access to "this".
+
+To access the class methods and class variables of a super class in an
+extended class, the class name prefix should be used just as from anywhere
+outside of the defining class: >
+
+ vim9script
+ class Vehicle
+ static var nextID: number = 1000
+ static def GetID(): number
+ nextID += 1
+ return nextID
+ enddef
+ endclass
+ class Car extends Vehicle
+ var myID: number
+ def new()
+ this.myID = Vehicle.GetID()
+ enddef
+ endclass
+<
+Class variables and methods are not inherited by a child class. A child class
+can declare a static variable or a method with the same name as the one in the
+super class. Depending on the class where the member is used the
+corresponding class member will be used. The type of the class member in a
+child class can be different from that in the super class.
+
+The double underscore (__) prefix for a class or object method name is
+reserved for future use.
+
+ *object-final-variable* *E1409*
+The |:final| keyword can be used to make a class or object variable a
+constant. Examples: >
+
+ class A
+ final v1 = [1, 2] # final object variable
+ public final v2 = {x: 1} # final object variable
+ static final v3 = 'abc' # final class variable
+ public static final v4 = 0z10 # final class variable
+ endclass
+<
+A final variable can be changed only from a constructor function. Example: >
+
+ class A
+ final v1: list<number>
+ def new()
+ this.v1 = [1, 2]
+ enddef
+ endclass
+ var a = A.new()
+ echo a.v1
+<
+Note that the value of a final variable can be changed. Example: >
+
+ class A
+ public final v1 = [1, 2]
+ endclass
+ var a = A.new()
+ a.v1[0] = 6 # OK
+ a.v1->add(3) # OK
+ a.v1 = [3, 4] # Error
+<
+ *E1408*
+Final variables are not supported in an interface. A class or object method
+cannot be final.
+
+ *object-const-variable*
+The |:const| keyword can be used to make a class or object variable and the
+value a constant. Examples: >
+
+ class A
+ const v1 = [1, 2] # const object variable
+ public const v2 = {x: 1} # const object variable
+ static const v3 = 'abc' # const class variable
+ public static const v4 = 0z10 # const class variable
+ endclass
+<
+A const variable can be changed only from a constructor function. Example: >
+
+ class A
+ const v1: list<number>
+ def new()
+ this.v1 = [1, 2]
+ enddef
+ endclass
+ var a = A.new()
+ echo a.v1
+<
+A const variable and its value cannot be changed. Example: >
+
+ class A
+ public const v1 = [1, 2]
+ endclass
+ var a = A.new()
+ a.v1[0] = 6 # Error
+ a.v1->add(3) # Error
+ a.v1 = [3, 4] # Error
+<
+ *E1410*
+Const variables are not supported in an interface. A class or object method
+cannot be a const.
+
+==============================================================================
+
+4. Using an abstract class *Vim9-abstract-class*
+
+An abstract class forms the base for at least one sub-class. In the class
+model one often finds that a few classes have the same properties that can be
+shared, but a class with these properties does not have enough state to create
+an object from. A sub-class must extend the abstract class and add the
+missing state and/or methods before it can be used to create objects for.
+
+For example, a Shape class could store a color and thickness. You cannot
+create a Shape object, it is missing the information about what kind of shape
+it is. The Shape class functions as the base for a Square and a Triangle
+class, for which objects can be created. Example: >
+
+ abstract class Shape
+ var color = Color.Black
+ var thickness = 10
+ endclass
+
+ class Square extends Shape
+ var size: number
+
+ def new(this.size)
+ enddef
+ endclass
+
+ class Triangle extends Shape
+ var base: number
+ var height: number
+
+ def new(this.base, this.height)
+ enddef
+ endclass
+<
+An abstract class is defined the same way as a normal class, except that it
+does not have any new() method. *E1359*
+
+ *abstract-method* *E1371* *E1372*
+An abstract method can be defined in an abstract class by using the "abstract"
+prefix when defining the method: >
+
+ abstract class Shape
+ abstract def Draw()
+ endclass
+<
+A static method in an abstract class cannot be an abstract method.
+
+ *E1373*
+A non-abstract class extending the abstract class must implement all the
+abstract methods. The signature (arguments, argument types and return type)
+must be exactly the same. If the return type of a method is a class, then
+that class or one of its subclasses can be used in the extended method.
+
+==============================================================================
+
+5. Using an interface *Vim9-using-interface*
+
+The example above with Shape, Square and Triangle can be made more useful if
+we add a method to compute the surface of the object. For that we create the
+interface called HasSurface, which specifies one method Surface() that returns
+a number. This example extends the one above: >
+
+ abstract class Shape
+ var color = Color.Black
+ var thickness = 10
+ endclass
+
+ interface HasSurface
+ def Surface(): number
+ endinterface
+
+ class Square extends Shape implements HasSurface
+ var size: number
+
+ def new(this.size)
+ enddef
+
+ def Surface(): number
+ return this.size * this.size
+ enddef
+ endclass
+
+ class 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
+ enddef
+ endclass
+<
+ *E1348* *E1349* *E1367* *E1382* *E1383*
+If a class declares to implement an interface, all the items specified in the
+interface must appear in the class, with the same types.
+
+The interface name can be used as a type: >
+
+ var shapes: list<HasSurface> = [
+ Square.new(12),
+ Triangle.new(8, 15),
+ ]
+ for shape in shapes
+ echo $'the surface is {shape.Surface()}'
+ endfor
+<
+ *E1378* *E1379* *E1380* *E1387*
+An interface can contain only object methods and read-only object variables.
+An interface cannot contain read-write or protected object variables,
+protected object methods, class variables and class methods.
+
+An interface can extend another interface using "extends". The sub-interface
+inherits all the instance variables and methods from the super interface.
+
+==============================================================================
+
+6. More class details *Vim9-class* *Class* *class*
+
+Defining a class ~
+ *:class* *:endclass* *:abstract*
+A class is defined between `:class` and `:endclass`. The whole class is
+defined in one script file. It is not possible to add to a class later.
+
+A class can only be defined in a |Vim9| script file. *E1316*
+A class cannot be defined inside a function.
+
+It is possible to define more than one class in a script file. Although it
+usually is better to export only one main class. It can be useful to define
+types, enums and helper classes though.
+
+The `:abstract` keyword may be prefixed and `:export` may be used. That gives
+these variants: >
+
+ class ClassName
+ endclass
+
+ export class ClassName
+ endclass
+
+ abstract class ClassName
+ endclass
+
+ export abstract class ClassName
+ endclass
+<
+ *E1314*
+The class name should be CamelCased. It must start with an uppercase letter.
+That avoids clashing with builtin types.
+ *E1315*
+After the class name these optional items can be used. Each can appear only
+once. They can appear in any order, although this order is recommended: >
+ extends ClassName
+ implements InterfaceName, OtherInterface
+ specifies SomeInterface
+< *E1355* *E1369*
+Each variable and method name can be used only once. It is not possible to
+define a method with the same name and different type of arguments. It is not
+possible to use a public and protected member variable with the same name. An
+object variable name used in a super class cannot be reused in a child class.
+
+
+Object Variable Initialization ~
+
+If the type of a variable is not explicitly specified in a class, then it is
+set to "any" during class definition. When an object is instantiated from the
+class, then the type of the variable is set.
+
+The following reserved keyword names cannot be used as an object or class
+variable name: "super", "this", "true", "false", "null", "null_blob",
+"null_dict", "null_function", "null_list", "null_partial", "null_string",
+"null_channel" and "null_job".
+
+Extending a class ~
+ *extends*
+A class can extend one other class. *E1352* *E1353* *E1354*
+The basic idea is to build on top of an existing class, add properties to it.
+
+The extended class is called the "base class" or "super class". The new class
+is called the "child class".
+
+Object variables from the base class are all taken over by the child class. It
+is not possible to override them (unlike some other languages).
+
+ *E1356* *E1357* *E1358*
+Object methods of the base class can be overruled. The signature (arguments,
+argument types and return type) must be exactly the same. If the return type
+of a method is a class, then that class or one of its subclasses can be used
+in the extended method. The method of the base class can be called by
+prefixing "super.".
+
+ *E1377*
+The access level of a method (public or protected) in a child class should be
+the same as the super class.
+
+Other object methods of the base class are taken over by the child class.
+
+Class methods, including methods starting with "new", can be overruled, like
+with object methods. The method on the base class can be called by prefixing
+the name of the class (for class methods) or "super.".
+
+Unlike other languages, the constructor of the base class does not need to be
+invoked. In fact, it cannot be invoked. If some initialization from the base
+class also needs to be done in a child class, put it in an object method and
+call that method from every constructor().
+
+If the base class did not specify a new() method then one was automatically
+created. This method will not be taken over by the child class. The child
+class can define its own new() method, or, if there isn't one, a new() method
+will be added automatically.
+
+
+A class implementing an interface ~
+ *implements* *E1346* *E1347* *E1389*
+A class can implement one or more interfaces. The "implements" keyword can
+only appear once *E1350* . Multiple interfaces can be specified, separated by
+commas. Each interface name can appear only once. *E1351*
+
+
+A class defining an interface ~
+ *specifies*
+A class can declare its interface, the object variables and methods, with a
+named interface. This avoids the need for separately specifying the
+interface, which is often done in many languages, especially Java.
+
+
+Items in a class ~
+ *E1318* *E1325* *E1388*
+Inside a class, in between `:class` and `:endclass`, these items can appear:
+- An object variable declaration: >
+ var _protectedVariableName: memberType
+ var readonlyVariableName: memberType
+ public var readwriteVariableName: memberType
+- A class variable declaration: >
+ static var _protectedClassVariableName: memberType
+ static var readonlyClassVariableName: memberType
+ public static var readwriteClassVariableName: memberType
+- A constructor method: >
+ def new(arguments)
+ def newName(arguments)
+- A class method: >
+ static def SomeMethod(arguments)
+ static def _ProtectedMethod(arguments)
+- An object method: >
+ def SomeMethod(arguments)
+ def _ProtectedMethod(arguments)
+
+For the object variable the type must be specified. The best way is to do
+this explicitly with ": {type}". For simple types you can also use an
+initializer, such as "= 123", and Vim will see that the type is a number.
+Avoid doing this for more complex types and when the type will be incomplete.
+For example: >
+ var nameList = []
+This specifies a list, but the item type is unknown. Better use: >
+ var nameList: list<string>
+The initialization isn't needed, the list is empty by default.
+ *E1330*
+Some types cannot be used, such as "void", "null" and "v:none".
+
+
+Defining an interface ~
+ *Interface* *:interface* *:endinterface*
+An interface is defined between `:interface` and `:endinterface`. It may be
+prefixed with `:export`: >
+
+ interface InterfaceName
+ endinterface
+
+ export interface InterfaceName
+ endinterface
+< *E1344*
+An interface can declare object variables, just like in a class but without
+any initializer.
+ *E1345*
+An interface can declare methods with `:def`, including the arguments and
+return type, but without the body and without `:enddef`. Example: >
+
+ interface HasSurface
+ var size: number
+ def Surface(): number
+ endinterface
+
+An interface name must start with an uppercase letter. *E1343*
+The "Has" prefix can be used to make it easier to guess this is an interface
+name, with a hint about what it provides.
+An interface can only be defined in a |Vim9| script file. *E1342*
+An interface cannot "implement" another interface but it can "extend" another
+interface. *E1381*
+
+
+null object ~
+
+When a variable is declared to have the type of an object, but it is not
+initialized, the value is null. When trying to use this null object Vim often
+does not know what class was supposed to be used. Vim then cannot check if
+a variable name is correct and you will get a "Using a null object" error,
+even when the variable name is invalid. *E1360* *E1362*
+
+
+Default constructor ~
+ *default-constructor*
+In case you define a class without a new() method, one will be automatically
+defined. This default constructor will have arguments for all the object
+variables, in the order they were specified. Thus if your class looks like: >
+
+ class AutoNew
+ var name: string
+ var age: number
+ var gender: Gender
+ endclass
+
+Then the default constructor will be: >
+
+ def new(this.name = v:none, this.age = v:none, this.gender = v:none)
+ enddef
+
+The "= v:none" default values make the arguments optional. Thus you can also
+call `new()` without any arguments. No assignment will happen and the default
+value for the object variables will be used. This is a more useful example,
+with default values: >
+
+ class TextPosition
+ var lnum: number = 1
+ var col: number = 1
+ endclass
+
+If you want the constructor to have mandatory arguments, you need to write it
+yourself. For example, if for the AutoNew class above you insist on getting
+the name, you can define the constructor like this: >
+
+ def new(this.name, this.age = v:none, this.gender = v:none)
+ enddef
+<
+When using the default new() method, if the order of the object variables in
+the class is changed later, then all the callers of the default new() method
+need to change. To avoid this, the new() method can be explicitly defined
+without any arguments.
+
+ *E1328*
+Note that you cannot use another default value than "v:none" here. If you
+want to initialize the object variables, do it where they are declared. This
+way you only need to look in one place for the default values.
+
+All object variables will be used in the default constructor, including
+protected access ones.
+
+If the class extends another one, the object variables of that class will come
+first.
+
+
+Multiple constructors ~
+ *multiple-constructors*
+Normally a class has just one new() constructor. In case you find that the
+constructor is often called with the same arguments you may want to simplify
+your code by putting those arguments into a second constructor method. For
+example, if you tend to use the color black a 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 of repeating the color every time you can add a constructor that
+includes it: >
+
+ def newBlack(this.garment, this.size)
+ this.color = Color.black
+ enddef
+ ...
+ var pants = newBlack(Garment.pants, "XL")
+ var shirt = newBlack(Garment.shirt, "XL")
+ var shoes = newBlack(Garment.shoes, "9.5")
+
+Note that the method name must start with "new". If there is no method called
+"new()" then the default constructor is added, even though there are other
+constructor methods.
+
+
+==============================================================================
+
+7. Type definition *typealias* *Vim9-type* *:type*
+
+ *E1393* *E1395* *E1396* *E1397* *E1398*
+A type definition is giving a name to a type specification. This is also
+known as a "type alias". The type alias can be used wherever a built-in type
+can be used. Example: >
+
+ type ListOfStrings = list<string>
+ var s: ListOfStrings = ['a', 'b']
+
+ def ProcessStr(str: ListOfStrings): ListOfStrings
+ return str
+ enddef
+ echo ProcessStr(s)
+<
+ *E1394*
+A type alias name must start with an upper case character. Only existing
+types can be aliased.
+
+ *E1399*
+A type alias can be created only at the script level and not inside a
+function. A type alias can be exported and used across scripts.
+
+ *E1400* *E1401* *E1402* *E1403* *E1407*
+A type alias cannot be used as an expression. A type alias cannot be used in
+the left-hand-side of an assignment.
+
+For a type alias name, the |typename()| function returns the type that is
+aliased: >
+
+ type ListOfStudents = list<dict<any>>
+ echo typename(ListOfStudents)
+ typealias<list<dict<any>>>
+<
+==============================================================================
+
+8. Enum *Vim9-enum* *:enum* *:endenum*
+
+{not implemented yet}
+
+An enum is a type that can have one of a list of values. Example: >
+
+ :enum Color
+ White
+ Red
+ Green
+ Blue
+ Black
+ :endenum
+
+
+==============================================================================
+
+9. Rationale
+
+Most of the choices for |Vim9| classes come from popular and recently
+developed languages, such as Java, TypeScript and Dart. The syntax has been
+made to fit with the way Vim script works, such as using `endclass` instead of
+using curly braces around the whole class.
+
+Some common constructs of object-oriented languages were chosen very long ago
+when this kind of programming was still new, and later found to be
+sub-optimal. By this time those constructs were widely used and changing them
+was not an option. In Vim we do have the freedom to make different choices,
+since classes are completely new. We can make the syntax simpler and more
+consistent than what "old" languages use. Without diverting too much, it
+should still mostly look like what you know from existing languages.
+
+Some recently developed languages add all kinds of fancy features that we
+don't need for Vim. But some have nice ideas that we do want to use.
+Thus we end up with a base of what is common in popular languages, dropping
+what looks like a bad idea, and adding some nice features that are easy to
+understand.
+
+The main rules we use to make decisions:
+- Keep it simple.
+- No surprises, mostly do what other languages are doing.
+- Avoid mistakes from the past.
+- Avoid the need for the script writer to consult the help to understand how
+ things work, most things should be obvious.
+- Keep it consistent.
+- Aim at an average size plugin, not at a huge project.
+
+
+Using new() for the constructor ~
+
+Many languages use the class name for the constructor method. A disadvantage
+is that quite often this is a long name. And when changing the class name all
+constructor methods need to be renamed. Not a big deal, but still a
+disadvantage.
+
+Other languages, such as TypeScript, use a specific name, such as
+"constructor()". That seems better. However, using "new" or "new()" to
+create a new object has no obvious relation with "constructor()".
+
+For |Vim9| script using the same method name for all constructors seemed like
+the right choice, and by calling it new() the relation between the caller and
+the method being called is obvious.
+
+
+No overloading of the constructor ~
+
+In Vim script, both legacy and |Vim9| script, there is no overloading of
+methods. That means it is not possible to use the same method name with
+different types of arguments. Therefore there also is only one new()
+constructor.
+
+With |Vim9| script it would be possible to support overloading, since
+arguments are typed. However, this gets complicated very quickly. Looking at
+a new() call one has to inspect the types of the arguments to know which of
+several new() methods is actually being called. And that can require
+inspecting quite a bit of code. For example, if one of the arguments is the
+return value of a method, you need to find that method to see what type it is
+returning.
+
+Instead, every constructor has to have a different name, starting with "new".
+That way multiple constructors with different arguments are possible, while it
+is very easy to see which constructor is being used. And the type of
+arguments can be properly checked.
+
+
+No overloading of methods ~
+
+Same reasoning as for the constructor: It is often not obvious what type
+arguments have, which would make it difficult to figure out what method is
+actually being called. Better just give the methods a different name, then
+type checking will make sure it works as you intended. This rules out
+polymorphism, which we don't really need anyway.
+
+
+Single inheritance and interfaces ~
+
+Some languages support multiple inheritance. Although that can be useful in
+some cases, it makes the rules of how a class works quite complicated.
+Instead, using interfaces to declare what is supported is much simpler. The
+very popular Java language does it this way, and it should be good enough for
+Vim. The "keep it simple" rule applies here.
+
+Explicitly declaring that a class supports an interface makes it easy to see
+what a class is intended for. It also makes it possible to do proper type
+checking. When an interface is changed any class that declares to implement
+it will be checked if that change was also changed. The mechanism to assume a
+class implements an interface just because the methods happen to match is
+brittle and leads to obscure problems, let's not do that.
+
+
+Using "this.variable" everywhere ~
+
+The object variables in various programming languages can often be accessed in
+different ways, depending on the location. Sometimes "this." has to be
+prepended to avoid ambiguity. They are usually declared without "this.".
+That is quite inconsistent and sometimes confusing.
+
+A very common issue is that in the constructor the arguments use the same name
+as the object variable. Then for these variables "this." needs to be prefixed
+in the body, while for other variables this is not needed and often omitted.
+This leads to a mix of variables with and without "this.", which is
+inconsistent.
+
+For |Vim9| classes the "this." prefix is always used for declared methods and
+variables. Simple and consistent. When looking at the code inside a class
+it's also directly clear which variable references are object variables and
+which aren't.
+
+
+Using class variables ~
+
+Using "static variable" to declare a class variable is very common, nothing
+new here. In |Vim9| script these can be accessed directly by their name.
+Very much like how a script-local variable can be used in a method. Since
+object variables are always accessed with "this." prepended, it's also quickly
+clear what kind of variable it is.
+
+TypeScript prepends the class name before the class variable name, also inside
+the class. This has two problems: The class name can be rather long, taking
+up quite a bit of space, and when the class is renamed all these places need
+to be changed too.
+
+
+Declaring object and class variables ~
+
+The main choice is whether to use "var" as with variable declarations.
+TypeScript does not use it: >
+ class Point {
+ x: number;
+ y = 0;
+ }
+
+Following that Vim object variables could be declared like this: >
+ class Point
+ this.x: number
+ this.y = 0
+ endclass
+
+Some users pointed out that this looks more like an assignment than a
+declaration. Adding "var" and omitting "this." changes that: >
+ class Point
+ var x: number
+ var y = 0
+ endclass
+
+We also need to be able to declare class variables using the "static" keyword.
+There we can also choose to leave out "var": >
+ class Point
+ var x: number
+ static count = 0
+ endclass
+
+Or do use it, before "static": >
+ class Point
+ var x: number
+ var static count = 0
+ endclass
+
+Or after "static": >
+ class Point
+ var x: number
+ static var count = 0
+ endclass
+
+This is more in line with "static def Func()".
+
+There is no clear preference whether to use "var" or not. The two main
+reasons to leave it out are:
+1. TypeScript and other popular languages do not use it.
+2. Less clutter.
+
+However, it is more common for languages to reuse their general variable and
+function declaration syntax for class/object variables and methods. Vim9 also
+reuses the general function declaration syntax for methods. So, for the sake
+of consistency, we require "var" in these declarations.
+
+
+Using "ClassName.new()" to construct an object ~
+
+Many languages use the "new" operator to create an object, which is actually
+kind of strange, since the constructor is defined as a method with arguments,
+not a command. TypeScript also has the "new" keyword, but the method is
+called "constructor()", it is hard to see the relation between the two.
+
+In |Vim9| script the constructor method is called new(), and it is invoked as
+new(), simple and straightforward. Other languages use "new ClassName()",
+while there is no ClassName() method, it's a method by another name in the
+class called ClassName. Quite confusing.
+
+
+Vim9class access modes ~
+ *vim9-access-modes*
+The variable access modes, and their meaning, supported by Vim9class are
+ |public-variable| read and write from anywhere
+ |read-only-variable| read from anywhere, write from inside the
+ class and sub-classes
+ |protected-variable| read and write from inside the class and
+ sub-classes
+
+The method access modes are similar, but without the read-only mode.
+
+
+Default read access to object variables ~
+
+Some users will remark that the access rules for object variables are
+asymmetric. Well, that is intentional. Changing a value is a very different
+action than reading a value. The read operation has no side effects, it can
+be done any number of times without affecting the object. Changing the value
+can have many side effects, and even have a ripple effect, affecting other
+objects.
+
+When adding object variables one usually doesn't think much about this, just
+get the type right. And normally the values are set in the new() method.
+Therefore defaulting to read access only "just works" in most cases. And when
+directly writing you get an error, which makes you wonder if you actually want
+to allow that. This helps writing code with fewer mistakes.
+
+
+Making object variables protected with an underscore ~
+
+When an object variable is protected, it can only be read and changed inside
+the class (and in sub-classes), then it cannot be used outside of the class.
+Prepending an underscore is a simple way to make that visible. Various
+programming languages have this as a recommendation.
+
+In case you change your mind and want to make the object variable accessible
+outside of the class, you will have to remove the underscore everywhere.
+Since the name only appears in the class (and sub-classes) they will be easy
+to find and change.
+
+The other way around is much harder: you can easily prepend an underscore to
+the object variable inside the class to make it protected, but any usage
+elsewhere you will have to track down and change. You may have to make it a
+"set" method call. This reflects the real world problem that taking away
+access 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 to
+reduce the number of keywords.
+
+
+No private object variables ~
+
+Some languages provide several ways to control access to object variables.
+The most known is "protected", and the meaning varies from language to
+language. Others are "shared", "private", "package" and even "friend".
+
+These rules make life more difficult. That can be justified in projects where
+many people work on the same, complex code where it is easy to make mistakes.
+Especially when refactoring or other changes to the class model.
+
+The Vim scripts are expected to be used in a plugin, with just one person or a
+small team working on it. Complex rules then only make it more complicated,
+the extra safety provided by the rules isn't really needed. Let's just keep
+it simple and not specify access details.
+
+
+==============================================================================
+
+10. To be done later
+
+Can a newSomething() constructor invoke another constructor? If yes, what are
+the restrictions?
+
+Thoughts:
+- Generics for a class: `class <Tkey, Tentry>`
+- Generics for a function: `def <Tkey> GetLast(key: Tkey)`
+- Mixins: not sure if that is useful, leave out for simplicity.
+
+Some things that look like good additions:
+- For testing: Mock mechanism
+
+An important class to be provided is "Promise". Since Vim is single
+threaded, connecting asynchronous operations is a natural way of allowing
+plugins to do their work without blocking the user. It's a uniform way to
+invoke callbacks and handle timeouts and errors.
+
+
+ vim:tw=78:ts=8:noet:ft=help:norl: