Object-oriented programming Reference

# Getting started

## Select the object-oriented programming paradigm

To undertake object-oriented programming (OOP) with Elan, you should first be reasonably familiar with procedural programming with Elan. Start by switching to the object-oriented paradigm from the menu at the top of the IDE. This will still allow you to do procedural programming, but changes two things:

- The list of demo programs will now show only programs that use OOP - except that Snake is offered in both procedural and object-oriented forms for direct comparison. We will be referring to code within the OOP demo programs within this text.
- It will change some of the options available on the new code menus in the editor:
  - At the global level, it will offer: concrete class and abstract class
  - Within a concrete class or abstract class the new code menu will show an entirely new list of instructions, collectively known as ‘members’ (plus comment) that may be defined within within them.

In the following section we will describe 10 principles that define the essence of OOP, illustrated with example code - where possible from the demo programs.

# Principles of object-oriented programming

Important. Every textbook on OOP differs slightly in the definition of core principles, and every language that supports OOP differs in the rules that it enforces. The following 10 principles are based on widely recognised best practices in OOP. When coding with Elan, in whichever of the supported languages - Python, VB, C#, or Java (or the Elan Reference Language) - these principles are, wherever possible, enforced by the Elan tooling. The resulting code is always valid syntax for the chosen language - but may depend upon common library methods defined in the Elan library. Also, if you go on to write code in any of those languages outside Elan, you will find that the same principles are not necessarily enforced. Though that might appear to offer you more freedom, sticking voluntarily to the principles that you learned in Elan will result in better code and fewer problems.

## A class is a user-defined data structure type

In procedural programming with Elan, there is a fixed set of types available to you to represent data - the only exception being enums which offer a very limited form of 'user-defined' type (UDT). OOP makes it easy to define far richer forms of UDTs. The simplest and most common way to do this is to define a concrete class which is one of the new options made available at global (file) level when using Elan with the object-oriented paradigm selected.

In the Snake object-oriented demo you can find three examples of concrete classes. Only the 'signature' of each class is shown here - not the instructions contained within the classes:
+class Snake Name? inheritance?40 +constructor(parameter definitions?) 41 new code end constructor +function toString name?(parameter definitions?) returns String Type? 42 return "undefined"value or expression?43 end function end class
+class Snake Name? inheritance?: # concrete class 44 +def __init__(self: Snake) -> None: 45 new code # end constructor +def toString name?(self: Snake) -> str Type?: # function method 46 return "undefined"value or expression?47 # end function method # end class
+class Snake Name? inheritance? {48 +public Snake(parameter definitions?) { 49 new code } // end constructor +public string Type? toString name?(parameter definitions?) { // function method 50 return "undefined"value or expression?;51 } // end function method } // end class
+Class Snake Name? inheritance?52 +Sub New(parameter definitions?) 53 new code End Sub +Function toString name?(parameter definitions?) As String Type? 54 Return "undefined"value or expression?55 End Function End Class
+class Snake Name? inheritance? {56 +public Snake(parameter definitions?) { 57 new code } // end constructor +public String Type? toString name?(parameter definitions?) { // function method 58 return "undefined"value or expression?;59 } // end function method } // end class

Within the definition of each class you will find several property instructions. Each property has unique name (within the class). A class may defined multiple properties of the same type, for example, the `SquareSquareSquareSquareSquare` class in Snake defines:

Name | Type
--- | ---
`xxxxx` | `IntintintIntegerint`
`yyyyy` | `IntintintIntegerint`

or properties may have different types, for example the `TuringMachineTuringMachineTuringMachineTuringMachineTuringMachine` class in the Roman Numerals Turing Machine demo has these:

Name | Type
--- | ---
`initialStateinitialStateinitialStateinitialStateinitialState` | `StringstrstringStringString`
`currentStatecurrentStatecurrentStatecurrentStatecurrentState` | `StringstrstringStringString`
`headPositionheadPositionheadPositionheadPositionheadPosition` | `IntintintIntegerint`
`haltStatehaltStatehaltStatehaltStatehaltState` | `StringstrstringStringString`
`rulesrulesrulesrulesrules` | `List<of Rule>list[Rule]List<Rule>List(Of Rule)List<Rule>`
`tapetapetapetapetape` | `StringstrstringStringString`

### Defining a class

Selecting concrete class from the new code menu inserts a template like this:

+class Name Name? inheritance?60 +constructor(parameter definitions parameter definitions?) 61 new code end constructor +function toString name?(parameter definitions parameter definitions?) returns String Type? 62 return "undefined"value or expression?63 end function end class
+class Name Name? inheritance?: # concrete class 64 +def __init__(self: Name) -> None: 65 new code # end constructor +def toString name?(self: Name) -> str Type?: # function method 66 return "undefined"value or expression?67 # end function method # end class
+class Name Name? inheritance? {68 +public Name(parameter definitions parameter definitions?) { 69 new code } // end constructor +public string Type? toString name?(parameter definitions parameter definitions?) { // function method 70 return "undefined"value or expression?;71 } // end function method } // end class
+Class Name Name? inheritance?72 +Sub New(parameter definitions parameter definitions?) 73 new code End Sub +Function toString name?(parameter definitions parameter definitions?) As String Type? 74 Return "undefined"value or expression?75 End Function End Class
+class Name Name? inheritance? {76 +public Name(parameter definitions parameter definitions?) { 77 new code } // end constructor +public String Type? toString name?(parameter definitions parameter definitions?) { // function method 78 return "undefined"value or expression?;79 } // end function method } // end class
where the only thing you must provide is a unique name for the class, which must start with a capital letter, followed by other letters, digits or underscores. (We will look at the roles of the constructor, and the toString function later on.)

## An object is an instance of a class

Every object in code is an instance of a specific class. The class may be thought of as a 'template' for defining instances. Each instance holds its own specific value for each of the properties defined in the class.

An new object may be created and assigned to a variable definition, for example:

variable apple name? set to new Apple()value or expression?80
apple name? = Apple()value or expression? # variable definition 81
var apple name? = new Apple()value or expression?;82
Dim apple name? = New Apple()value or expression? ' variable definition 83
var apple name? = new Apple()value or expression?;84
variable snake name? set to new Snake()value or expression?85
snake name? = Snake()value or expression? # variable definition 86
var snake name? = new Snake()value or expression?;87
Dim snake name? = New Snake()value or expression? ' variable definition 88
var snake name? = new Snake()value or expression?;89

Note that the type of each variable is determined by the class of the instance so that the `appleappleappleappleapple` variable may subsequently be reassigned to a different instance of `AppleAppleAppleAppleApple` but may not be reassigned to an instance of a different class (nor any other type).

A new instance may also be created as part of an expression without having to be assigned to a variable, for example:

+function emptyPoint name?(parameter definitions parameter definitions?) returns Point Type? 90 return new Point(-1, -1)value or expression?91 end function
+def emptyPoint name?(parameter definitions parameter definitions?) -> Point Type?: # function 92 return Point(-1, -1)value or expression?93 # end function
+static Point Type? emptyPoint name?(parameter definitions parameter definitions?) { // function 94 return new Point(-1, -1)value or expression?;95 } // end function
+Function emptyPoint name?(parameter definitions parameter definitions?) As Point Type? 96 Return New Point(-1, -1)value or expression?97 End Function
+static Point Type? emptyPoint name?(parameter definitions parameter definitions?) { // function 98 return new Point(-1, -1)value or expression?;99 } // end function

### Reading properties

Wherever you have a reference to an object, your code may read and make use of the publicly-visible properties of that object using 'dot syntax', for example (from the Pathfinder demo):

+if distViaCurrent < neighbour.distFromStart condition? then 100 new code end if
+if distViaCurrent < neighbour.distFromStart condition?: 101 new code # end if
+if (distViaCurrent < neighbour.distFromStart condition?) { 102 new code } // end if
+If distViaCurrent < neighbour.distFromStart condition? Then 103 new code End If
+if (distViaCurrent < neighbour.distFromStart condition?) { 104 new code } // end if
is comparing the value of the variable `distViaCurrentdistViaCurrentdistViaCurrentdistViaCurrentdistViaCurrent` to the property named `distFromStartdistFromStartdistFromStartdistFromStartdistFromStart` of the object named `neighbourneighbourneighbourneighbourneighbour`.

## The constructor initialises the properties

When coding with Elan every class must define a constructor, the template for which is created when you define a new class, and which may be edited, though not deleted. The role of the constructor is to initialise the properties whenever an instance of that class is created.

The only properties that don't need to be initialised are properties of type `IntintintIntegerint`, `FloatfloatdoubleDoubledouble`, or `BooleanboolboolBooleanboolean` - which are automatically initialised to the default value of each type - `00000`, `0.00.00.00.00.0`, or `falseFalsefalseFalsefalse` respectively. All other properties must be explicitly initialised within the constructor. Here is simple example of properties being initialised within the constructor for `SquareSquareSquareSquareSquare` in the Snake demo:

+class Square Name? inheritance?105 +constructor(x as Int, y as Int parameter definitions?) 106 assign this.x variableName? to x value or expression?107 assign this.y variableName? to y value or expression?108 end constructor property x name? as Int Type?109 property y name? as Int Type?110 # Methods not shown here comment? +function toString name?(parameter definitions parameter definitions?) returns String Type? 111 return "{this.x}, {this.y}"value or expression?112 end function end class
+class Square Name? inheritance?: # concrete class 113 +def __init__(self: Square, x: int, y: int parameter definitions?) -> None: 114 self.x variableName? = x value or expression? # assignment 115 self.y variableName? = y value or expression? # assignment 116 # end constructor x name?: int Type? # property 117 y name?: int Type? # property 118 # Methods not shown here comment? +def toString name?(self: Square) -> str Type?: # function method 119 return "{this.x}, {this.y}"value or expression?120 # end function method # end class
+class Square Name? inheritance? {121 +public Square(int x, int y parameter definitions?) { 122 this.x variableName? = x value or expression?; // assignment 123 this.y variableName? = y value or expression?; // assignment 124 } // end constructor public int Type? x name? {get; private set;} // property 125 public int Type? y name? {get; private set;} // property 126 // Methods not shown here comment? +public string Type? toString name?(parameter definitions parameter definitions?) { // function method 127 return "{this.x}, {this.y}"value or expression?;128 } // end function method } // end class
+Class Square Name? inheritance?129 +Sub New(x As Integer, y As Integer parameter definitions?) 130 Me.x variableName? = x value or expression? ' assignment 131 Me.y variableName? = y value or expression? ' assignment 132 End Sub Property x name? As Integer Type?133 Property y name? As Integer Type?134 ' Methods not shown here comment? +Function toString name?(parameter definitions parameter definitions?) As String Type? 135 Return "{this.x}, {this.y}"value or expression?136 End Function End Class
+class Square Name? inheritance? {137 +public Square(int x, int y parameter definitions?) { 138 this.x variableName? = x value or expression?; // assignment 139 this.y variableName? = y value or expression?; // assignment 140 } // end constructor public int Type? x name?; // property 141 public int Type? y name?; // property 142 // Methods not shown here comment? +public String Type? toString name?(parameter definitions parameter definitions?) { // function method 143 return "{this.x}, {this.y}"value or expression?;144 } // end function method } // end class

### Note:

- Even properties that are automatically initialised may be explicitly initialised in the constructor.
- It is quite common to initialise strings to an empty string - `""""""""""` and a list to any empty list of the appropriate member-type, for example `new List<of Int>()list[int]()new List<int>()New List(Of Integer)()new List<int>()` - though you may choose any value.
- If you don't you want every instance of a class to be initialised with the same value, the specific value for an instance is specified via paramaters added into the constructor definition.
- When a new instance is created, arguments for each parameter must be specified (as they would be for a procedure or function), so creating a new `SquareSquareSquareSquareSquare` for example takes the form `variable tailname? set to new Square(20, 15)value or expression?0tailname? = Square(20, 15)value or expression? # variable definition1var tailname? = new Square(20, 15)value or expression?;2Dim tailname? = New Square(20, 15)value or expression? ' variable definition3var tailname? = new Square(20, 15)value or expression?;4`
- A property is initialised within the construction using a reassign variable instruction - since a property may be thought of as a named variable that holds a value specific to each instance of the class.
- the name of the property being reassigned must be prefixed by this self Me this Me followed by a dot.

## Objects may have associations to other objects

So far we have looked at properties where the type is one of the standard library types. However, a class may define one or more properties where the type is a class - either of the same type as the class in which the property is defined, or - more commonly - of a different class. Each such property is referred to as an 'association' or 'associated object'. If the type of a property is a list, or other data structure, where the member type is a class, then it is often referred to as a 'multiple association' - with the ordinary kind of association referred to as 'single association'. The `SnakeSnakeSnakeSnakeSnake` class shows both kinds of association (only relevant parts of the class are shown only here):

+class Snake Name? inheritance?145 +constructor(parameter definitions parameter definitions?) 146 variable tail name? set to new Square(20, 15)value or expression?147 assign this.currentDir variableName? to Direction.right value or expression?148 assign this.body variableName? to [tail]value or expression?149 assign this.head variableName? to tail.getAdjacentSquare(this.currentDir)value or expression?150 assign this.priorTail variableName? to tail value or expression?151 end constructor private property currentDir name? as Direction Type?152 private property head name? as Square Type?153 private property body name? as List<of Square>Type?154 private property priorTail name? as Square Type?155 +function toString name?(parameter definitions?) returns String Type? 156 return "undefined"value or expression?157 end function end class
+class Snake Name? inheritance?: # concrete class 158 +def __init__(self: Snake) -> None: 159 tail name? = Square(20, 15)value or expression? # variable definition 160 self.currentDir variableName? = Direction.right value or expression? # assignment 161 self.body variableName? = [tail]value or expression? # assignment 162 self.head variableName? = tail.getAdjacentSquare(self.currentDir)value or expression? # assignment 163 self.priorTail variableName? = tail value or expression? # assignment 164 # end constructor currentDir name?: Direction Type? # private property 165 head name?: Square Type? # private property 166 body name?: list[Square]Type? # private property 167 priorTail name?: Square Type? # private property 168 +def toString name?(self: Snake) -> str Type?: # function method 169 return "undefined"value or expression?170 # end function method # end class
+class Snake Name? inheritance? {171 +public Snake(parameter definitions parameter definitions?) { 172 var tail name? = new Square(20, 15)value or expression?;173 this.currentDir variableName? = Direction.right value or expression?; // assignment 174 this.body variableName? = new [] {tail}value or expression?; // assignment 175 this.head variableName? = tail.getAdjacentSquare(this.currentDir)value or expression?; // assignment 176 this.priorTail variableName? = tail value or expression?; // assignment 177 } // end constructor private Direction Type? currentDir name? {get; private set;} // private property 178 private Square Type? head name? {get; private set;} // private property 179 private List<Square>Type? body name? {get; private set;} // private property 180 private Square Type? priorTail name? {get; private set;} // private property 181 +public string Type? toString name?(parameter definitions?) { // function method 182 return "undefined"value or expression?;183 } // end function method } // end class
+Class Snake Name? inheritance?184 +Sub New(parameter definitions parameter definitions?) 185 Dim tail name? = New Square(20, 15)value or expression? ' variable definition 186 Me.currentDir variableName? = Direction.right value or expression? ' assignment 187 Me.body variableName? = {tail}value or expression? ' assignment 188 Me.head variableName? = tail.getAdjacentSquare(Me.currentDir)value or expression? ' assignment 189 Me.priorTail variableName? = tail value or expression? ' assignment 190 End Sub Private Property currentDir name? As Direction Type?191 Private Property head name? As Square Type?192 Private Property body name? As List(Of Square)Type?193 Private Property priorTail name? As Square Type?194 +Function toString name?(parameter definitions?) As String Type? 195 Return "undefined"value or expression?196 End Function End Class
+class Snake Name? inheritance? {197 +public Snake(parameter definitions parameter definitions?) { 198 var tail name? = new Square(20, 15)value or expression?;199 this.currentDir variableName? = Direction.right value or expression?; // assignment 200 this.body variableName? = list(tail)value or expression?; // assignment 201 this.head variableName? = tail.getAdjacentSquare(this.currentDir)value or expression?; // assignment 202 this.priorTail variableName? = tail value or expression?; // assignment 203 } // end constructor private Direction Type? currentDir name?; // private property 204 private Square Type? head name?; // private property 205 private List<Square>Type? body name?; // private property 206 private Square Type? priorTail name?; // private property 207 +public String Type? toString name?(parameter definitions?) { // function method 208 return "undefined"value or expression?;209 } // end function method } // end class

### Note:

- The`SnakeSnakeSnakeSnakeSnake` is always initialised to the same values, so the constructor does not need to define any parameters.
- The `currentDircurrentDircurrentDircurrentDircurrentDir` property is of type `DirectionDirectionDirectionDirectionDirection` (which is an enum) and is initialised to `Direction.rightDirection.rightDirection.rightDirection.rightDirection.right`.
- The `bodybodybodybodybody` property is a multiple association - defined as a list of type `SquareSquareSquareSquareSquare`
- The constructor defines a variable `tailtailtailtailtail` used only for the purpose of initialising properties. It is first used to initialise the `bodybodybodybodybody` as a list containing only the `tailtailtailtailtail` and is finally used to define the `priorTailpriorTailpriorTailpriorTailpriorTail` which is a single association of type `SquareSquareSquareSquareSquare`. In between it is used in an expression to determine the initial value for the `headheadheadheadhead` property using a function (more on this in the next heading).
- It is thus legitimate to call functions within the constructor. A constructor may not call any procedure, however. And you should avoid doing any work in a constructor other than determining appropriate values for initialising its properties.

## Classes provide behaviour through methods

In the last code example `tail.getAdjacentSquare(this.currentDir)tail.getAdjacentSquare(self.currentDir)tail.getAdjacentSquare(this.currentDir)tail.getAdjacentSquare(Me.currentDir)tail.getAdjacentSquare(this.currentDir)` calls a function method, using 'dot syntax' on the the variable `tailtailtailtailtail`, which is an instance of class `SquareSquareSquareSquareSquare`. Defining a function method, or a procedure method, on a class has these advantages:

- they are invoked on an instance using 'dot-syntax' as we shown in the previous example
- they have access to all the properties belonging to that same instance, and can also invoke other methods on the same object, in both cases prefixed by this self Me this Me dot.

Properties on a class define the data (or 'state') for each instance of the class; methods define the behaviour for the object.

## A function method provides information based on the parameters specified in combination with the object's properties

Function methods defined on a class, are similar to global functions in that they act like 'queries', returning information that is determined by the values of the parameters. The difference is that a function method defined on a class, may additionally make use of information obtained from the properties of the object (directly or indirectly) - to determine the information to be returned. But like a global function, a function method defined on a class may not cause any side effects, which means that it may not update any property. The body of the getAdjacentSquare accesses the objects `xxxxx` and `yyyyy` properties and uses this, together with the `DirectionDirectionDirectionDirectionDirection` parameter to create and return a new instance of `SquareSquareSquareSquareSquare` with different `xxxxx` and `yyyyy` properties:

+function getAdjacentSquare name?(d as Direction parameter definitions?) returns Square Type? 210 variable newX name? set to this.x value or expression?211 variable newY name? set to this.y value or expression?212 +if d is Direction.left condition? then 213 assign newX variableName? to this.x - 1 value or expression?214 elif d is Direction.right condition? then 215 assign newX variableName? to this.x + 1 value or expression?216 elif d is Direction.up condition? then 217 assign newY variableName? to this.y - 1 value or expression?218 elif d is Direction.down condition? then 219 assign newY variableName? to this.y + 1 value or expression?220 end if return new Square(newX, newY)value or expression?221 end function
+def getAdjacentSquare name?(d: Direction parameter definitions?) -> Square Type?: # function 222 newX name? = self.x value or expression? # variable definition 223 newY name? = self.y value or expression? # variable definition 224 +if d == Direction.left condition?: 225 newX variableName? = self.x - 1 value or expression? # assignment 226 elif d == Direction.right condition?: # else if 227 newX variableName? = self.x + 1 value or expression? # assignment 228 elif d == Direction.up condition?: # else if 229 newY variableName? = self.y - 1 value or expression? # assignment 230 elif d == Direction.down condition?: # else if 231 newY variableName? = self.y + 1 value or expression? # assignment 232 # end if return Square(newX, newY)value or expression?233 # end function
+static Square Type? getAdjacentSquare name?(Direction d parameter definitions?) { // function 234 var newX name? = this.x value or expression?;235 var newY name? = this.y value or expression?;236 +if (d == Direction.left condition?) { 237 newX variableName? = this.x - 1 value or expression?; // assignment 238 } else if (d == Direction.right condition?) {239 newX variableName? = this.x + 1 value or expression?; // assignment 240 } else if (d == Direction.up condition?) {241 newY variableName? = this.y - 1 value or expression?; // assignment 242 } else if (d == Direction.down condition?) {243 newY variableName? = this.y + 1 value or expression?; // assignment 244 } // end if return new Square(newX, newY)value or expression?;245 } // end function
+Function getAdjacentSquare name?(d As Direction parameter definitions?) As Square Type? 246 Dim newX name? = Me.x value or expression? ' variable definition 247 Dim newY name? = Me.y value or expression? ' variable definition 248 +If d = Direction.left condition? Then 249 newX variableName? = Me.x - 1 value or expression? ' assignment 250 ElseIf d = Direction.right condition? Then 251 newX variableName? = Me.x + 1 value or expression? ' assignment 252 ElseIf d = Direction.up condition? Then 253 newY variableName? = Me.y - 1 value or expression? ' assignment 254 ElseIf d = Direction.down condition? Then 255 newY variableName? = Me.y + 1 value or expression? ' assignment 256 End If Return New Square(newX, newY)value or expression?257 End Function
+static Square Type? getAdjacentSquare name?(Direction d parameter definitions?) { // function 258 var newX name? = this.x value or expression?;259 var newY name? = this.y value or expression?;260 +if (d == Direction.left condition?) { 261 newX variableName? = this.x - 1 value or expression?; // assignment 262 } else if (d == Direction.right condition?) {263 newX variableName? = this.x + 1 value or expression?; // assignment 264 } else if (d == Direction.up condition?) {265 newY variableName? = this.y - 1 value or expression?; // assignment 266 } else if (d == Direction.down condition?) {267 newY variableName? = this.y + 1 value or expression?; // assignment 268 } // end if return new Square(newX, newY)value or expression?;269 } // end function

The toString function method returns a string that represents the object in some way. It is called automatically whenever you call print with a variable that holds an instance of the class. If you don't need to print an object in text form on the display, it is safe to leave the default implementation toString - that was created when you added the class, and which returns an empty string `""""""""""`. If you do intend to print an object in text form then you can define the string to be returned, incorporating one or more of the object's properties to help identify the particular object. For example, you might edit the method defined on the `SnakeSnakeSnakeSnakeSnake` class to:

+function toString name?(parameter definitions parameter definitions?) returns String Type? 270 return $"A snake with {this.body.length() + 1} segments"value or expression?271 end function
+def toString name?(parameter definitions parameter definitions?) -> str Type?: # function 272 return f"A snake with {self.body.length() + 1} segments"value or expression?273 # end function
+static string Type? toString name?(parameter definitions parameter definitions?) { // function 274 return $"A snake with {this.body.length() + 1} segments"value or expression?;275 } // end function
+Function toString name?(parameter definitions parameter definitions?) As String Type? 276 Return $"A snake with {Me.body.length() + 1} segments"value or expression?277 End Function
+static String Type? toString name?(parameter definitions parameter definitions?) { // function 278 return String.format("A snake with % segments", this.body.length() + 1)value or expression?;279 } // end function
(You might like to try this out, temporarilyadding the instruction `print(snakearguments?)5print(snakearguments?)6Console.WriteLine(snakearguments?); // print statement7Console.WriteLine(snakearguments?) ' print statement8System.out.println(snakearguments?); // print statement9` into the main routine.)

## A procedure method changes the state of the object, and/or interacts with the system

Procedure methods, like function methods, may define parameters and may also read the values of the object's properties. Like global procedures they may also generate side effects, and this includes changing the values of the object's properties, and may call other procedures, on the same object, or associated objects. For example, the clockTick procedure method defined in the `SnakeSnakeSnakeSnakeSnake` class, changes the position of various segments, and, if the `headheadheadheadhead` now covers the same space as the `appleappleappleappleapple` changes the position of the apple (passed into the method as a parameter) by calling the newRandomPosition procedure method on `appleappleappleappleapple`:

+procedure clockTick name?(key as String, apple as Apple parameter definitions?) 280 call this.setDirection procedureName?(key arguments?)281 assign this.priorTail variableName? to this.body[0]value or expression?282 variable body name? set to this.body value or expression?283 call body.append procedureName?(this.head arguments?)284 assign this.head variableName? to this.head.getAdjacentSquare(this.currentDir)value or expression?285 +if this.head.equals(apple.location)condition? then 286 call apple.newRandomPosition procedureName?(this arguments?)287 else 288 assign this.body variableName? to this.body.subList(1, this.body.length())value or expression?289 end if end procedure
+def clockTick name?(key: str, apple: Apple parameter definitions?) -> None: # procedure 290 self.setDirection procedureName?(key arguments?) # procedure call 291 self.priorTail variableName? = self.body[0]value or expression? # assignment 292 body name? = self.body value or expression? # variable definition 293 body.append procedureName?(self.head arguments?) # procedure call 294 self.head variableName? = self.head.getAdjacentSquare(self.currentDir)value or expression? # assignment 295 +if self.head.equals(apple.location)condition?: 296 apple.newRandomPosition procedureName?(self arguments?) # procedure call 297 else:298 self.body variableName? = self.body.subList(1, self.body.length())value or expression? # assignment 299 # end if # end procedure
+static void clockTick name?(string key, Apple apple parameter definitions?) { // procedure 300 this.setDirection procedureName?(key arguments?); // procedure call 301 this.priorTail variableName? = this.body[0]value or expression?; // assignment 302 var body name? = this.body value or expression?;303 body.append procedureName?(this.head arguments?); // procedure call 304 this.head variableName? = this.head.getAdjacentSquare(this.currentDir)value or expression?; // assignment 305 +if (this.head.equals(apple.location)condition?) { 306 apple.newRandomPosition procedureName?(this arguments?); // procedure call 307 } else {308 this.body variableName? = this.body.subList(1, this.body.length())value or expression?; // assignment 309 } // end if } // end procedure
+Sub clockTick name?(key As String, apple As Apple parameter definitions?) ' procedure 310 Me.setDirection procedureName?(key arguments?) ' procedure call 311 Me.priorTail variableName? = Me.body(0)value or expression? ' assignment 312 Dim body name? = Me.body value or expression? ' variable definition 313 body.append procedureName?(Me.head arguments?) ' procedure call 314 Me.head variableName? = Me.head.getAdjacentSquare(Me.currentDir)value or expression? ' assignment 315 +If Me.head.equals(apple.location)condition? Then 316 apple.newRandomPosition procedureName?(Me arguments?) ' procedure call 317 Else 318 Me.body variableName? = Me.body.subList(1, Me.body.length())value or expression? ' assignment 319 End If End Sub
+static void clockTick name?(String key, Apple apple parameter definitions?) { // procedure 320 this.setDirection procedureName?(key arguments?); // procedure call 321 this.priorTail variableName? = this.body[0]value or expression?; // assignment 322 var body name? = this.body value or expression?;323 body.append procedureName?(this.head arguments?); // procedure call 324 this.head variableName? = this.head.getAdjacentSquare(this.currentDir)value or expression?; // assignment 325 +if (this.head.equals(apple.location)condition?) { 326 apple.newRandomPosition procedureName?(this arguments?); // procedure call 327 } else {328 this.body variableName? = this.body.subList(1, this.body.length())value or expression?; // assignment 329 } // end if } // end procedure

## Objects should represent the principal nouns in the application domain

The word 'encapsulation' is often used in descriptions of object-oriented programming. But that word has two rather different meanings in plain English. Fortunately, both of the meanings of 'encapsulation' apply.

The first meaning of encapsulation is similar to 'represents' - as in 'Our school motto encapsulates the ethos and culture of the school'. (The second meaning will be addressed in the next principle.) Thus, objects should represent, or encapsulate, the principal concepts in the application domain. A rule of thumb is that the classes defined in a program should correspond to the main nouns used when describing the purpose and operation of the program in plain English. You can see this in the Snake demo, where the code defines three classes, named `SnakeSnakeSnakeSnakeSnake`, `AppleAppleAppleAppleApple`, and `SquareSquareSquareSquareSquare` - all nouns that would be recognised by anyone who understands how to play the game Snake, but who does not necessarily know anything about programming.

One of the claimed benefits of this is that it makes programs easier to read, and to update in response to new requirements, because the structure of the code corresponds more closely to the language of the application domain. If the user, or the business customer that owns the game, says that they want the snake to be a different colour, or for there to be two apples at once (in different positions) - it will be easier for the programmer to identity where within the program the code must be changed that in a procedural implementation. You can try this for yourself, by asking a user to specify similar small changes to the presentation and/or game rules, and testing how long it takes you to update the procedural, and object-oriented, versions of the Snake program as required.

Importantly, the class does not just represent all the information associated with the noun - it also encapsulates the behaviour needed from that thing, in the form of methods. This is sometimes stated as representing the know-whats for the thing (as properties), and the know how-to's as methods.

## Objects should hide state behind methods, where possible

This principle corresponds to the second meaning of 'encapsulation': sealing. Think of the related word: 'capsule'. You can only access the capabilities of an object through its public members. All the 'members' defined on a class (that is: its properties and methods) are public - although properties are public only for reading, not for modifying. However, it is possible to make any property or method private - such that it can be accessed from code within the class, but not from outside. To do this, you bring up the context menu on the instruction (by right-mouse-click or Ctrl-m) and select make private (a change that can be reversed with make public).A method might be made private because it just provides help to one or more public methods, but is not expected to be useful in its own right. However, a property is often made private to implement the principle of 'information' hiding.

Some textbooks suggest that every property - for example `dateOfBirthdateOfBirthdateOfBirthdateOfBirthdateOfBirth` - should be private, and that access should be via a 'getter' - a function method typically named getDateOfBirth, and a 'setter' - a procedure method typically named setDateOfBirth. But that idea is not really hiding the information. Real information hiding is to prevent external code from accessing the data and instead provide them with public methods that provide more useful services. For example, in the Snake demo, all the `headheadheadheadhead` and `bodybodybodybodybody` properties are private, but the function method bodyCovers allows external code to test whether the snake (body or head) covers a given square, passed in as a parameter. This method is called from within the newRandomPosition defined by the `AppleAppleAppleAppleApple` class, to ensure that the next apple is not created directly underneath the snake.

## A concrete class may optionally inherit from an abstract class

In many applications two or more of the classes will be seen as having quite a lot in common. When this situation identified, there might be a case for making them inherit from a common 'abstract' class. For example, in a school administration system, you might define classes named Pupil, Teacher, and Parent, but these might all inherit from a common abstract class named Individual. The Person class can then be described as the 'superclass' of the other three, and they as the 'subclasses' of Individual.

An abstract class is created, at global level, with an abstract class instruction, and the template requires a name (beginning with a capital letter) to be specified.

The main differences between an abstract and a concrete super-class are:

- an abstract class cannot be instantiated. If, using the example above, you were to write: `new Individual()Individual()new Individual()New Individual()new Individual()` you will get a compile-error message: Individual must be concrete to create instance.
- an abstract class has no constructor (it also does not need toString because every concrete class must define one.
- the new code menus, as well as offering the property, procedure method, and function method options as in a concrete class, also offer abstract procedure method, and abstract function method. A concrete class must provide a concrete (normal) implementation of each abstract member defined in its superclass, or any abstract class above it in the hierarchy.

Earlier we learned about association between objects. Association may be characterised by the 'has a' relationship, as in a 'Student has a personal tutor' (meaning that the Student class defines a property named 'tutor' - which is of type Teacher. Bt contrast inheritance may be characterised as an 'is a' relationship, as in 'a Student is an Individual'.

There are two principal motivations from making two or more classes inherit from a common abstract class:

- To reduce repetition of common properties and methods - which may be defined on the abstract superclass and then not repeated in the subclasses. For example it might be that Individual define a (string) property named 'emailAddress' and define a common procedure method named 'sendMessage'.
- To allow instances of any of the subclasses to be handled by external code without having to know the individual subclass of each instance. This principle is known as 'type substitutability' and is a form of a more general principle know as 'polymorphism' - meaning 'of multiple forms'. For example, the user might define a special interest group that included some pupils, parents, and teachers, and so would be defined as a list of type Individual. This then makes it easy to send a message to all the members of the group, by invoking the method 'sendMessage' on each member in turn, without having to identify the type each member.

Some textbooks emphasise the first of those two motivations, but it is the second one that is far more important. Indeed, inheritance is the most over-used, and the most frequently abused, concepts in OOP. For that reason, irrespective of the programming language being used, Elan deliberately enforces principles of good OOP from the outset. For example:

- Each class may inherit from one superclass only
- The superclass must be an abstract class - no class may inherit from another concrete class.
- A abstract class may inherit from another abstract class - to form a 'hierarchy' of abstraction, if desired.
- A concrete class may inherit concrete (ordinary) members from its superclass, but it may not override them.

The last point is controversial - since all the supported programming languages allow overriding. But overriding (of concrete methods) breaks the 'O' of the widely-quoted 'SOLID' principles of oop: that classes should be 'Open for extension, but closed for modification'.

## Application logic should be well-distributed across classes

In Elan, an object-oriented program still needs a procedural main method to execute.

The Java language is unusual in that even the main routine must defined within a class - Elan handles this by including a class named Global as part of the file boilerplate, but treats the instructions directly within this class as being 'global' in nature. Any user-defined classes are added within this, and Elan does not allow properties to be added directly within that Global class since these would be, effectively, just global variables in disguise.

In general good OOP design means aiming to keep the functionality well-distributed among the user-defined classes. Inevitably, some classes are going to define more methods, and/or more-complex methods, than others. But you should be wary of a situation where one class is doing most of the work, and the other classes act as little more than data structures without encapsulated behaviour. All too often that one big class is instantiated only once (this pattern is known as a 'singleton'), by the main routine. While singletons are not always a bad idea, a singleton that does most of the work of the program - sometimes irreverently referred to as a 'god class' - is really just a procedural program in disguise.

A useful check on your design is to look at the distribution of instructions in the program (not counting instructions within tests, which are not part of the executable program). For example, the Snake - object-oriented demo has a total of 96 instructions (excluding tests), of which just 12 are not in a user-defined class (they are all in the main routine). The allocation of the other instructions is as follows:

Class | Properties | Methods (excl. constructor & toString) | No. of instructions | Notes
--- | --- | --- | --- | ---
`SnakeSnakeSnakeSnakeSnake` | 4 | 6 | 57 | singleton - but an extended version of the game might have multiple instances.
`AppleAppleAppleAppleApple` | 1 | 2 | 16 | ditto
`SquareSquareSquareSquareSquare` | 2 | 2 | 22 | Many instances created in the game. Both Snake and Apple have associations to one or more Squares

# Global Instructions

Coding with Elan using the object-oriented paradigm offers all the global instructions uses in the procedural paradigm plus two new ones: concrete class and abstract class

## Concrete class

### Examples of a concrete class

From the Snake - object-oriented demo:

+class Apple Name? inheritance?330 +constructor(parameter definitions parameter definitions?) 331 assign this.location variableName? to new Square(0, 0)value or expression?332 end constructor property location name? as Square Type?333 +procedure newRandomPosition name?(snake as Snake parameter definitions?) 334 variable changePosition name? set to true value or expression?335 +while changePosition condition? 336 variable ranX name? set to randint(0, 39)value or expression?337 variable ranY name? set to randint(0, 29)value or expression?338 assign this.location variableName? to new Square(ranX, ranY)value or expression?339 +if not snake.bodyCovers(this.location)condition? then 340 assign changePosition variableName? to false value or expression?341 end if end while end procedure +procedure updateBlocks name?(blocks as List<of List<of Int>>parameter definitions?) 342 assign blocks[this.location.x][this.location.y]variableName? to red value or expression?343 end procedure +function toString name?(parameter definitions parameter definitions?) returns String Type? 344 return $"an Apple at {this.location}"value or expression?345 end function end class
+class Apple Name? inheritance?: # concrete class 346 +def __init__(self: Apple) -> None: 347 self.location variableName? = Square(0, 0)value or expression? # assignment 348 # end constructor location name?: Square Type? # property 349 +def newRandomPosition name?(self: Apple, snake: Snake parameter definitions?) -> None: # procedure method 350 changePosition name? = True value or expression? # variable definition 351 +while changePosition condition?: 352 ranX name? = randint(0, 39)value or expression? # variable definition 353 ranY name? = randint(0, 29)value or expression? # variable definition 354 self.location variableName? = Square(ranX, ranY)value or expression? # assignment 355 +if not snake.bodyCovers(self.location)condition?: 356 changePosition variableName? = False value or expression? # assignment 357 # end if # end while # end procedure method +def updateBlocks name?(self: Apple, blocks: list[list[int]]parameter definitions?) -> None: # procedure method 358 blocks[self.location.x][self.location.y]variableName? = red value or expression? # assignment 359 # end procedure method +def toString name?(self: Apple) -> str Type?: # function method 360 return f"an Apple at {self.location}"value or expression?361 # end function method # end class
+class Apple Name? inheritance? {362 +public Apple(parameter definitions parameter definitions?) { 363 this.location variableName? = new Square(0, 0)value or expression?; // assignment 364 } // end constructor public Square Type? location name? {get; private set;} // property 365 +public void newRandomPosition name?(Snake snake parameter definitions?) { // procedure method 366 var changePosition name? = true value or expression?;367 +while (changePosition condition?) { 368 var ranX name? = randint(0, 39)value or expression?;369 var ranY name? = randint(0, 29)value or expression?;370 this.location variableName? = new Square(ranX, ranY)value or expression?; // assignment 371 +if (!snake.bodyCovers(this.location)condition?) { 372 changePosition variableName? = false value or expression?; // assignment 373 } // end if } // end while } // end procedure method +public void updateBlocks name?(List<List<int>> blocks parameter definitions?) { // procedure method 374 blocks[this.location.x][this.location.y]variableName? = red value or expression?; // assignment 375 } // end procedure method +public string Type? toString name?(parameter definitions parameter definitions?) { // function method 376 return $"an Apple at {this.location}"value or expression?;377 } // end function method } // end class
+Class Apple Name? inheritance?378 +Sub New(parameter definitions parameter definitions?) 379 Me.location variableName? = New Square(0, 0)value or expression? ' assignment 380 End Sub Property location name? As Square Type?381 +Sub newRandomPosition name?(snake As Snake parameter definitions?) ' procedure method 382 Dim changePosition name? = True value or expression? ' variable definition 383 +While changePosition condition? 384 Dim ranX name? = randint(0, 39)value or expression? ' variable definition 385 Dim ranY name? = randint(0, 29)value or expression? ' variable definition 386 Me.location variableName? = New Square(ranX, ranY)value or expression? ' assignment 387 +If Not snake.bodyCovers(Me.location)condition? Then 388 changePosition variableName? = False value or expression? ' assignment 389 End If End While End Sub +Sub updateBlocks name?(blocks As List(Of List(Of Integer))parameter definitions?) ' procedure method 390 blocks(Me.location.x)(Me.location.y)variableName? = red value or expression? ' assignment 391 End Sub +Function toString name?(parameter definitions parameter definitions?) As String Type? 392 Return $"an Apple at {Me.location}"value or expression?393 End Function End Class
+class Apple Name? inheritance? {394 +public Apple(parameter definitions parameter definitions?) { 395 this.location variableName? = new Square(0, 0)value or expression?; // assignment 396 } // end constructor public Square Type? location name?; // property 397 +public void newRandomPosition name?(Snake snake parameter definitions?) { // procedure method 398 var changePosition name? = true value or expression?;399 +while (changePosition condition?) { 400 var ranX name? = randint(0, 39)value or expression?;401 var ranY name? = randint(0, 29)value or expression?;402 this.location variableName? = new Square(ranX, ranY)value or expression?; // assignment 403 +if (!snake.bodyCovers(this.location)condition?) { 404 changePosition variableName? = false value or expression?; // assignment 405 } // end if } // end while } // end procedure method +public void updateBlocks name?(List<List<int>> blocks parameter definitions?) { // procedure method 406 blocks[this.location.x][this.location.y]variableName? = red value or expression?; // assignment 407 } // end procedure method +public String Type? toString name?(parameter definitions parameter definitions?) { // function method 408 return String.format("an Apple at %", this.location)value or expression?;409 } // end function method } // end class

From the Blackjack demo:

+class Card Name? inheritance?410 property suit name? as Suit Type?411 property rank name? as String Type?412 property faceDown name? as Boolean Type?413 +constructor(rank as String, suit as Suit, facedown as Boolean parameter definitions?) 414 assign this.rank variableName? to rank value or expression?415 assign this.suit variableName? to suit value or expression?416 assign this.faceDown variableName? to facedown value or expression?417 end constructor +procedure turnFaceUp name?(parameter definitions parameter definitions?) 418 assign this.faceDown variableName? to false value or expression?419 end procedure +procedure turnFaceDown name?(parameter definitions parameter definitions?) 420 assign this.faceDown variableName? to true value or expression?421 end procedure +function toString name?(parameter definitions parameter definitions?) returns String Type? 422 return $"{this.rank}{symbolForSuit(this.suit)}"value or expression?423 end function end class
+class Card Name? inheritance?: # concrete class 424 suit name?: Suit Type? # property 425 rank name?: str Type? # property 426 faceDown name?: bool Type? # property 427 +def __init__(self: Card, rank: str, suit: Suit, facedown: bool parameter definitions?) -> None: 428 self.rank variableName? = rank value or expression? # assignment 429 self.suit variableName? = suit value or expression? # assignment 430 self.faceDown variableName? = facedown value or expression? # assignment 431 # end constructor +def turnFaceUp name?(self: Card) -> None: # procedure method 432 self.faceDown variableName? = False value or expression? # assignment 433 # end procedure method +def turnFaceDown name?(self: Card) -> None: # procedure method 434 self.faceDown variableName? = True value or expression? # assignment 435 # end procedure method +def toString name?(self: Card) -> str Type?: # function method 436 return f"{self.rank}{symbolForSuit(self.suit)}"value or expression?437 # end function method # end class
+class Card Name? inheritance? {438 public Suit Type? suit name? {get; private set;} // property 439 public string Type? rank name? {get; private set;} // property 440 public bool Type? faceDown name? {get; private set;} // property 441 +public Card(string rank, Suit suit, bool facedown parameter definitions?) { 442 this.rank variableName? = rank value or expression?; // assignment 443 this.suit variableName? = suit value or expression?; // assignment 444 this.faceDown variableName? = facedown value or expression?; // assignment 445 } // end constructor +public void turnFaceUp name?(parameter definitions parameter definitions?) { // procedure method 446 this.faceDown variableName? = false value or expression?; // assignment 447 } // end procedure method +public void turnFaceDown name?(parameter definitions parameter definitions?) { // procedure method 448 this.faceDown variableName? = true value or expression?; // assignment 449 } // end procedure method +public string Type? toString name?(parameter definitions parameter definitions?) { // function method 450 return $"{this.rank}{symbolForSuit(this.suit)}"value or expression?;451 } // end function method } // end class
+Class Card Name? inheritance?452 Property suit name? As Suit Type?453 Property rank name? As String Type?454 Property faceDown name? As Boolean Type?455 +Sub New(rank As String, suit As Suit, facedown As Boolean parameter definitions?) 456 Me.rank variableName? = rank value or expression? ' assignment 457 Me.suit variableName? = suit value or expression? ' assignment 458 Me.faceDown variableName? = facedown value or expression? ' assignment 459 End Sub +Sub turnFaceUp name?(parameter definitions parameter definitions?) ' procedure method 460 Me.faceDown variableName? = False value or expression? ' assignment 461 End Sub +Sub turnFaceDown name?(parameter definitions parameter definitions?) ' procedure method 462 Me.faceDown variableName? = True value or expression? ' assignment 463 End Sub +Function toString name?(parameter definitions parameter definitions?) As String Type? 464 Return $"{Me.rank}{symbolForSuit(Me.suit)}"value or expression?465 End Function End Class
+class Card Name? inheritance? {466 public Suit Type? suit name?; // property 467 public String Type? rank name?; // property 468 public boolean Type? faceDown name?; // property 469 +public Card(String rank, Suit suit, boolean facedown parameter definitions?) { 470 this.rank variableName? = rank value or expression?; // assignment 471 this.suit variableName? = suit value or expression?; // assignment 472 this.faceDown variableName? = facedown value or expression?; // assignment 473 } // end constructor +public void turnFaceUp name?(parameter definitions parameter definitions?) { // procedure method 474 this.faceDown variableName? = false value or expression?; // assignment 475 } // end procedure method +public void turnFaceDown name?(parameter definitions parameter definitions?) { // procedure method 476 this.faceDown variableName? = true value or expression?; // assignment 477 } // end procedure method +public String Type? toString name?(parameter definitions parameter definitions?) { // function method 478 return String.format("%%", this.rank, symbolForSuit(this.suit))value or expression?;479 } // end function method } // end class

From the Pathfinder demo:

+class Point Name? inheritance?480 property x name? as Int Type?481 property y name? as Int Type?482 property isEmpty name? as Boolean Type?483 +constructor(x as Int, y as Int parameter definitions?) 484 +if (x < 0) or (y < 0)condition? then 485 assign this.isEmpty variableName? to true value or expression?486 else 487 assign this.x variableName? to x value or expression?488 assign this.y variableName? to y value or expression?489 end if end constructor +function minDistTo name?(p as Point parameter definitions?) returns Float Type? 490 return sqrt(pow((p.x - this.x), 2) + pow((p.y - this.y), 2))value or expression?491 end function +function isAdjacentTo name?(p as Point parameter definitions?) returns Boolean Type? 492 return (this.minDistTo(p) is 1) or (this.minDistTo(p).round(4) is sqrt(2).round(4))value or expression?493 end function # Returns the 8 theoretically-neighbouring points, whether or not within bounds comment? +function neighbouringPoints name?(parameter definitions parameter definitions?) returns List<of Point>Type? 494 return [new Point(this.x - 1, this.y - 1), new Point(this.x, this.y - 1), new Point(this.x + 1, this.y - 1), new Point(this.x - 1, this.y), new Point(this.x + 1, this.y), new Point(this.x - 1, this.y + 1), new Point(this.x, this.y + 1), new Point(this.x + 1, this.y + 1)]value or expression?495 end function +function toString name?(parameter definitions parameter definitions?) returns String Type? 496 return $"{this.x},{this.y}"value or expression?497 end function end class
+class Point Name? inheritance?: # concrete class 498 x name?: int Type? # property 499 y name?: int Type? # property 500 isEmpty name?: bool Type? # property 501 +def __init__(self: Point, x: int, y: int parameter definitions?) -> None: 502 +if (x < 0) or (y < 0)condition?: 503 self.isEmpty variableName? = True value or expression? # assignment 504 else:505 self.x variableName? = x value or expression? # assignment 506 self.y variableName? = y value or expression? # assignment 507 # end if # end constructor +def minDistTo name?(self: Point, p: Point parameter definitions?) -> float Type?: # function method 508 return sqrt(pow((p.x - self.x), 2) + pow((p.y - self.y), 2))value or expression?509 # end function method +def isAdjacentTo name?(self: Point, p: Point parameter definitions?) -> bool Type?: # function method 510 return (self.minDistTo(p) == 1) or (self.minDistTo(p).round(4) == sqrt(2).round(4))value or expression?511 # end function method # Returns the 8 theoretically-neighbouring points, whether or not within bounds comment? +def neighbouringPoints name?(self: Point) -> list[Point]Type?: # function method 512 return [Point(self.x - 1, self.y - 1), Point(self.x, self.y - 1), Point(self.x + 1, self.y - 1), Point(self.x - 1, self.y), Point(self.x + 1, self.y), Point(self.x - 1, self.y + 1), Point(self.x, self.y + 1), Point(self.x + 1, self.y + 1)]value or expression?513 # end function method +def toString name?(self: Point) -> str Type?: # function method 514 return f"{self.x},{self.y}"value or expression?515 # end function method # end class
+class Point Name? inheritance? {516 public int Type? x name? {get; private set;} // property 517 public int Type? y name? {get; private set;} // property 518 public bool Type? isEmpty name? {get; private set;} // property 519 +public Point(int x, int y parameter definitions?) { 520 +if ((x < 0) || (y < 0)condition?) { 521 this.isEmpty variableName? = true value or expression?; // assignment 522 } else {523 this.x variableName? = x value or expression?; // assignment 524 this.y variableName? = y value or expression?; // assignment 525 } // end if } // end constructor +public double Type? minDistTo name?(Point p parameter definitions?) { // function method 526 return sqrt(pow((p.x - this.x), 2) + pow((p.y - this.y), 2))value or expression?;527 } // end function method +public bool Type? isAdjacentTo name?(Point p parameter definitions?) { // function method 528 return (this.minDistTo(p) == 1) || (this.minDistTo(p).round(4) == sqrt(2).round(4))value or expression?;529 } // end function method // Returns the 8 theoretically-neighbouring points, whether or not within bounds comment? +public List<Point>Type? neighbouringPoints name?(parameter definitions parameter definitions?) { // function method 530 return new [] {new Point(this.x - 1, this.y - 1), new Point(this.x, this.y - 1), new Point(this.x + 1, this.y - 1), new Point(this.x - 1, this.y), new Point(this.x + 1, this.y), new Point(this.x - 1, this.y + 1), new Point(this.x, this.y + 1), new Point(this.x + 1, this.y + 1)}value or expression?;531 } // end function method +public string Type? toString name?(parameter definitions parameter definitions?) { // function method 532 return $"{this.x},{this.y}"value or expression?;533 } // end function method } // end class
+Class Point Name? inheritance?534 Property x name? As Integer Type?535 Property y name? As Integer Type?536 Property isEmpty name? As Boolean Type?537 +Sub New(x As Integer, y As Integer parameter definitions?) 538 +If (x < 0) Or (y < 0)condition? Then 539 Me.isEmpty variableName? = True value or expression? ' assignment 540 Else 541 Me.x variableName? = x value or expression? ' assignment 542 Me.y variableName? = y value or expression? ' assignment 543 End If End Sub +Function minDistTo name?(p As Point parameter definitions?) As Double Type? 544 Return sqrt(pow((p.x - Me.x), 2) + pow((p.y - Me.y), 2))value or expression?545 End Function +Function isAdjacentTo name?(p As Point parameter definitions?) As Boolean Type? 546 Return (Me.minDistTo(p) = 1) Or (Me.minDistTo(p).round(4) = sqrt(2).round(4))value or expression?547 End Function ' Returns the 8 theoretically-neighbouring points, whether or not within bounds comment? +Function neighbouringPoints name?(parameter definitions parameter definitions?) As List(Of Point)Type? 548 Return {New Point(Me.x - 1, Me.y - 1), New Point(Me.x, Me.y - 1), New Point(Me.x + 1, Me.y - 1), New Point(Me.x - 1, Me.y), New Point(Me.x + 1, Me.y), New Point(Me.x - 1, Me.y + 1), New Point(Me.x, Me.y + 1), New Point(Me.x + 1, Me.y + 1)}value or expression?549 End Function +Function toString name?(parameter definitions parameter definitions?) As String Type? 550 Return $"{Me.x},{Me.y}"value or expression?551 End Function End Class
+class Point Name? inheritance? {552 public int Type? x name?; // property 553 public int Type? y name?; // property 554 public boolean Type? isEmpty name?; // property 555 +public Point(int x, int y parameter definitions?) { 556 +if ((x < 0) || (y < 0)condition?) { 557 this.isEmpty variableName? = true value or expression?; // assignment 558 } else {559 this.x variableName? = x value or expression?; // assignment 560 this.y variableName? = y value or expression?; // assignment 561 } // end if } // end constructor +public double Type? minDistTo name?(Point p parameter definitions?) { // function method 562 return sqrt(pow((p.x - this.x), 2) + pow((p.y - this.y), 2))value or expression?;563 } // end function method +public boolean Type? isAdjacentTo name?(Point p parameter definitions?) { // function method 564 return (this.minDistTo(p) == 1) || (this.minDistTo(p).round(4) == sqrt(2).round(4))value or expression?;565 } // end function method // Returns the 8 theoretically-neighbouring points, whether or not within bounds comment? +public List<Point>Type? neighbouringPoints name?(parameter definitions parameter definitions?) { // function method 566 return list(new Point(this.x - 1, this.y - 1), new Point(this.x, this.y - 1), new Point(this.x + 1, this.y - 1), new Point(this.x - 1, this.y), new Point(this.x + 1, this.y), new Point(this.x - 1, this.y + 1), new Point(this.x, this.y + 1), new Point(this.x + 1, this.y + 1))value or expression?;567 } // end function method +public String Type? toString name?(parameter definitions parameter definitions?) { // function method 568 return String.format("%,%", this.x, this.y)value or expression?;569 } // end function method } // end class

### What you need to know about a concrete class

- A concrete class is a type of user-defined data-structure that holds data in properties, as well as methods to provide behaviour.
- A new class is defined by adding a concrete class instruction at global level, which requires a name (starting with an initial capital) to be specified
- All concrete classes must define a constructor, and a toString method, but the template for the class provides minimal valid implementations of these which you may expand or modify.
- You create an instance of the class using the class name and providing any require arguments (as specified by the class' constructor) for example: `variable applename? set to new Apple()value or expression?10applename? = Apple()value or expression? # variable definition11var applename? = new Apple()value or expression?;12Dim applename? = New Apple()value or expression? ' variable definition13var applename? = new Apple()value or expression?;14` or `variable startname? set to new Point(5, 5)value or expression?15startname? = Point(5, 5)value or expression? # variable definition16var startname? = new Point(5, 5)value or expression?;17Dim startname? = New Point(5, 5)value or expression? ' variable definition18var startname? = new Point(5, 5)value or expression?;19`.
- All properties must be initialised within the constructor (except for numeric or Boolean properties which have the default value for their type until changed)
- Function methods provide information derived from the properties of the instance, and or from parameters provided to it.
- toString is an ordinary function method but with a specific name; it is called if an instance of the class is printed, or inserted into an interpolated string; typically toString will include one or more of the object's properties.
- Procedure methods make changes to the properties of the instance and/or depend on the system in some way.
- Any property or method may be made private (using an action on the context menu for the instruction), such that it may ony be accessed by code within the same class.
- Once you have an instance in a variable you can access its public methods using dot-syntax; however, properties may be only be read by external code - to modify properties from outside you need to go through a procedure method defined on that class.
- A class may optionally inherit from a single abstract class.

## Abstract class

### Example of an abstract class

From the Blackjack demo, the abstract class `PlayerPlayerPlayerPlayerPlayer` - which is inherited by the concrete classes `HumanPlayerHumanPlayerHumanPlayerHumanPlayerHumanPlayer` and `DealerDealerDealerDealerDealer` - defines public concrete properties, public concrete methods, plus three abstract methods, two of which are accompanied by private 'helper' methods to which subclasses may delegate part or all of their implementations.

+abstract class Player Name? inheritance?570 property name name? as String Type?571 property points name? as Int Type?572 property cards name? as List<of Card>Type?573 property handTotal name? as Int Type?574 property softAce name? as Boolean Type?575 property status name? as Status Type?576 property hasTurn name? as Boolean Type?577 +procedure startTurn name?(parameter definitions parameter definitions?) 578 +if this.status is Status.active condition? then 579 assign this.hasTurn variableName? to true value or expression?580 end if end procedure +procedure determineOutcomeAndUpdatePoints name?(dealer as Dealer parameter definitions?) 581 variable playerOutcome name? set to determinePlayerOutcome(dealer, this)value or expression?582 +if playerOutcome is Outcome.winDouble condition? then 583 call this.changePointsBy procedureName?(2 arguments?)584 call dealer.changePointsBy procedureName?(-2 arguments?)585 elif playerOutcome is Outcome.win condition? then 586 call this.changePointsBy procedureName?(1 arguments?)587 call dealer.changePointsBy procedureName?(-1 arguments?)588 elif playerOutcome is Outcome.lose condition? then 589 call this.changePointsBy procedureName?(-1 arguments?)590 call dealer.changePointsBy procedureName?(1 arguments?)591 end if end procedure +procedure evaluateStatus name?(newCard as Card parameter definitions?) 592 +if (this.cardCount() is 2) and (this.handTotal is 21)condition? then 593 assign this.status variableName? to Status.blackjack value or expression?594 elif (this.handTotal > 21) and (this.softAce)condition? then 595 assign this.handTotal variableName? to this.handTotal - 10 value or expression?596 assign this.softAce variableName? to false value or expression?597 elif this.handTotal > 21 condition? then 598 assign this.status variableName? to Status.bust value or expression?599 elif this.handTotal is 21 condition? then 600 assign this.status variableName? to Status.standing value or expression?601 end if +if this.status isnt Status.active condition? then 602 assign this.hasTurn variableName? to false value or expression?603 end if end procedure +procedure stand name?(parameter definitions parameter definitions?) 604 assign this.status variableName? to Status.standing value or expression?605 assign this.hasTurn variableName? to false value or expression?606 end procedure +procedure draw name?(parameter definitions parameter definitions?) 607 variable newCard name? set to dealCard(random())value or expression?608 variable cards name? set to this.cards value or expression?609 call cards.append procedureName?(newCard arguments?)610 +if newCard.rank.equals("A")condition? then 611 call this.addAce procedureName?(arguments?)612 else 613 assign this.handTotal variableName? to this.handTotal + rankValue()[newCard.rank]value or expression?614 end if call this.evaluateStatus procedureName?(newCard arguments?)615 end procedure +procedure addAce name?(parameter definitions parameter definitions?) 616 +if this.softAce condition? then 617 assign this.handTotal variableName? to this.handTotal + 1 value or expression?618 else 619 assign this.handTotal variableName? to this.handTotal + 11 value or expression?620 assign this.softAce variableName? to true value or expression?621 end if end procedure +function cardCount name?(parameter definitions parameter definitions?) returns Int Type? 622 return this.cards.length()value or expression?623 end function +procedure changePointsBy name?(amount as Int parameter definitions?) 624 assign this.points variableName? to this.points + amount value or expression?625 end procedure abstract procedure newHand name?(parameter definitions parameter definitions?)626 +private procedure newHandHelper name?(parameter definitions parameter definitions?) 627 assign this.hasTurn variableName? to false value or expression?628 assign this.softAce variableName? to false value or expression?629 assign this.cards variableName? to new List<of Card>()value or expression?630 assign this.handTotal variableName? to 0 value or expression?631 assign this.status variableName? to Status.active value or expression?632 call this.draw procedureName?(arguments?)633 call this.draw procedureName?(arguments?)634 end procedure abstract function getMessage name?(parameter definitions parameter definitions?) returns String Type?635 +private function getMessageHelper name?(parameter definitions parameter definitions?) returns String Type? 636 variable msg name? set to ""value or expression?637 variable status name? set to this.status value or expression?638 +if this.hasTurn condition? then 639 assign msg variableName? to msg + " - PLAYING"value or expression?640 elif status is Status.standing condition? then 641 assign msg variableName? to msg + " - STANDING"value or expression?642 elif status is Status.blackjack condition? then 643 assign msg variableName? to msg + " - BLACKJACK"value or expression?644 elif status is Status.bust condition? then 645 assign msg variableName? to msg + " - BUST"value or expression?646 end if return msg value or expression?647 end function abstract procedure nextAction name?(dealerFaceCard as Card parameter definitions?)648 end abstract class
+class Player Name?(ABC) inheritance?: # abstract class 649 name name?: str Type? # property 650 points name?: int Type? # property 651 cards name?: list[Card]Type? # property 652 handTotal name?: int Type? # property 653 softAce name?: bool Type? # property 654 status name?: Status Type? # property 655 hasTurn name?: bool Type? # property 656 +def startTurn name?(self: Player) -> None: # procedure method 657 +if self.status == Status.active condition?: 658 self.hasTurn variableName? = True value or expression? # assignment 659 # end if # end procedure method +def determineOutcomeAndUpdatePoints name?(self: Player, dealer: Dealer parameter definitions?) -> None: # procedure method 660 playerOutcome name? = determinePlayerOutcome(dealer, self)value or expression? # variable definition 661 +if playerOutcome == Outcome.winDouble condition?: 662 self.changePointsBy procedureName?(2 arguments?) # procedure call 663 dealer.changePointsBy procedureName?(-2 arguments?) # procedure call 664 elif playerOutcome == Outcome.win condition?: # else if 665 self.changePointsBy procedureName?(1 arguments?) # procedure call 666 dealer.changePointsBy procedureName?(-1 arguments?) # procedure call 667 elif playerOutcome == Outcome.lose condition?: # else if 668 self.changePointsBy procedureName?(-1 arguments?) # procedure call 669 dealer.changePointsBy procedureName?(1 arguments?) # procedure call 670 # end if # end procedure method +def evaluateStatus name?(self: Player, newCard: Card parameter definitions?) -> None: # procedure method 671 +if (self.cardCount() == 2) and (self.handTotal == 21)condition?: 672 self.status variableName? = Status.blackjack value or expression? # assignment 673 elif (self.handTotal > 21) and (self.softAce)condition?: # else if 674 self.handTotal variableName? = self.handTotal - 10 value or expression? # assignment 675 self.softAce variableName? = False value or expression? # assignment 676 elif self.handTotal > 21 condition?: # else if 677 self.status variableName? = Status.bust value or expression? # assignment 678 elif self.handTotal == 21 condition?: # else if 679 self.status variableName? = Status.standing value or expression? # assignment 680 # end if +if self.status != Status.active condition?: 681 self.hasTurn variableName? = False value or expression? # assignment 682 # end if # end procedure method +def stand name?(self: Player) -> None: # procedure method 683 self.status variableName? = Status.standing value or expression? # assignment 684 self.hasTurn variableName? = False value or expression? # assignment 685 # end procedure method +def draw name?(self: Player) -> None: # procedure method 686 newCard name? = dealCard(random())value or expression? # variable definition 687 cards name? = self.cards value or expression? # variable definition 688 cards.append procedureName?(newCard arguments?) # procedure call 689 +if newCard.rank.equals("A")condition?: 690 self.addAce procedureName?(arguments?) # procedure call 691 else:692 self.handTotal variableName? = self.handTotal + rankValue()[newCard.rank]value or expression? # assignment 693 # end if self.evaluateStatus procedureName?(newCard arguments?) # procedure call 694 # end procedure method +def addAce name?(self: Player) -> None: # procedure method 695 +if self.softAce condition?: 696 self.handTotal variableName? = self.handTotal + 1 value or expression? # assignment 697 else:698 self.handTotal variableName? = self.handTotal + 11 value or expression? # assignment 699 self.softAce variableName? = True value or expression? # assignment 700 # end if # end procedure method +def cardCount name?(self: Player) -> int Type?: # function method 701 return self.cards.length()value or expression?702 # end function method +def changePointsBy name?(self: Player, amount: int parameter definitions?) -> None: # procedure method 703 self.points variableName? = self.points + amount value or expression? # assignment 704 # end procedure method @abstractmethod
def newHand name?(parameter definitions parameter definitions?) -> None
pass # abstract procedure 705 +def newHandHelper name?(self: Player) -> None: # private procedure method 706 self.hasTurn variableName? = False value or expression? # assignment 707 self.softAce variableName? = False value or expression? # assignment 708 self.cards variableName? = list[Card]()value or expression? # assignment 709 self.handTotal variableName? = 0 value or expression? # assignment 710 self.status variableName? = Status.active value or expression? # assignment 711 self.draw procedureName?(arguments?) # procedure call 712 self.draw procedureName?(arguments?) # procedure call 713 # end procedure method @abstractmethod
def getMessage name?(parameter definitions parameter definitions?) -> str Type?:
pass # abstract function 714 +def getMessageHelper name?(self: Player) -> str Type?: # private function method 715 msg name? = ""value or expression? # variable definition 716 status name? = self.status value or expression? # variable definition 717 +if self.hasTurn condition?: 718 msg variableName? = msg + " - PLAYING"value or expression? # assignment 719 elif status == Status.standing condition?: # else if 720 msg variableName? = msg + " - STANDING"value or expression? # assignment 721 elif status == Status.blackjack condition?: # else if 722 msg variableName? = msg + " - BLACKJACK"value or expression? # assignment 723 elif status == Status.bust condition?: # else if 724 msg variableName? = msg + " - BUST"value or expression? # assignment 725 # end if return msg value or expression?726 # end function method @abstractmethod
def nextAction name?(dealerFaceCard: Card parameter definitions?) -> None
pass # abstract procedure 727 # end class
+abstract class Player Name? inheritance? {728 public string Type? name name? {get; private set;} // property 729 public int Type? points name? {get; private set;} // property 730 public List<Card>Type? cards name? {get; private set;} // property 731 public int Type? handTotal name? {get; private set;} // property 732 public bool Type? softAce name? {get; private set;} // property 733 public Status Type? status name? {get; private set;} // property 734 public bool Type? hasTurn name? {get; private set;} // property 735 +public void startTurn name?(parameter definitions parameter definitions?) { // procedure method 736 +if (this.status == Status.active condition?) { 737 this.hasTurn variableName? = true value or expression?; // assignment 738 } // end if } // end procedure method +public void determineOutcomeAndUpdatePoints name?(Dealer dealer parameter definitions?) { // procedure method 739 var playerOutcome name? = determinePlayerOutcome(dealer, this)value or expression?;740 +if (playerOutcome == Outcome.winDouble condition?) { 741 this.changePointsBy procedureName?(2 arguments?); // procedure call 742 dealer.changePointsBy procedureName?(-2 arguments?); // procedure call 743 } else if (playerOutcome == Outcome.win condition?) {744 this.changePointsBy procedureName?(1 arguments?); // procedure call 745 dealer.changePointsBy procedureName?(-1 arguments?); // procedure call 746 } else if (playerOutcome == Outcome.lose condition?) {747 this.changePointsBy procedureName?(-1 arguments?); // procedure call 748 dealer.changePointsBy procedureName?(1 arguments?); // procedure call 749 } // end if } // end procedure method +public void evaluateStatus name?(Card newCard parameter definitions?) { // procedure method 750 +if ((this.cardCount() == 2) && (this.handTotal == 21)condition?) { 751 this.status variableName? = Status.blackjack value or expression?; // assignment 752 } else if ((this.handTotal > 21) && (this.softAce)condition?) {753 this.handTotal variableName? = this.handTotal - 10 value or expression?; // assignment 754 this.softAce variableName? = false value or expression?; // assignment 755 } else if (this.handTotal > 21 condition?) {756 this.status variableName? = Status.bust value or expression?; // assignment 757 } else if (this.handTotal == 21 condition?) {758 this.status variableName? = Status.standing value or expression?; // assignment 759 } // end if +if (this.status != Status.active condition?) { 760 this.hasTurn variableName? = false value or expression?; // assignment 761 } // end if } // end procedure method +public void stand name?(parameter definitions parameter definitions?) { // procedure method 762 this.status variableName? = Status.standing value or expression?; // assignment 763 this.hasTurn variableName? = false value or expression?; // assignment 764 } // end procedure method +public void draw name?(parameter definitions parameter definitions?) { // procedure method 765 var newCard name? = dealCard(random())value or expression?;766 var cards name? = this.cards value or expression?;767 cards.append procedureName?(newCard arguments?); // procedure call 768 +if (newCard.rank.equals("A")condition?) { 769 this.addAce procedureName?(arguments?); // procedure call 770 } else {771 this.handTotal variableName? = this.handTotal + rankValue()[newCard.rank]value or expression?; // assignment 772 } // end if this.evaluateStatus procedureName?(newCard arguments?); // procedure call 773 } // end procedure method +public void addAce name?(parameter definitions parameter definitions?) { // procedure method 774 +if (this.softAce condition?) { 775 this.handTotal variableName? = this.handTotal + 1 value or expression?; // assignment 776 } else {777 this.handTotal variableName? = this.handTotal + 11 value or expression?; // assignment 778 this.softAce variableName? = true value or expression?; // assignment 779 } // end if } // end procedure method +public int Type? cardCount name?(parameter definitions parameter definitions?) { // function method 780 return this.cards.length()value or expression?;781 } // end function method +public void changePointsBy name?(int amount parameter definitions?) { // procedure method 782 this.points variableName? = this.points + amount value or expression?; // assignment 783 } // end procedure method abstract void newHand name?(parameter definitions parameter definitions?); // abstract procedure 784 +protected void newHandHelper name?(parameter definitions parameter definitions?) { // private procedure method 785 this.hasTurn variableName? = false value or expression?; // assignment 786 this.softAce variableName? = false value or expression?; // assignment 787 this.cards variableName? = new List<Card>()value or expression?; // assignment 788 this.handTotal variableName? = 0 value or expression?; // assignment 789 this.status variableName? = Status.active value or expression?; // assignment 790 this.draw procedureName?(arguments?); // procedure call 791 this.draw procedureName?(arguments?); // procedure call 792 } // end procedure method abstract string Type? getMessage name?(parameter definitions parameter definitions?); // abstract function 793 +protected string Type? getMessageHelper name?(parameter definitions parameter definitions?) { // private function method 794 var msg name? = ""value or expression?;795 var status name? = this.status value or expression?;796 +if (this.hasTurn condition?) { 797 msg variableName? = msg + " - PLAYING"value or expression?; // assignment 798 } else if (status == Status.standing condition?) {799 msg variableName? = msg + " - STANDING"value or expression?; // assignment 800 } else if (status == Status.blackjack condition?) {801 msg variableName? = msg + " - BLACKJACK"value or expression?; // assignment 802 } else if (status == Status.bust condition?) {803 msg variableName? = msg + " - BUST"value or expression?; // assignment 804 } // end if return msg value or expression?;805 } // end function method abstract void nextAction name?(Card dealerFaceCard parameter definitions?); // abstract procedure 806 } // end class
+MustInherit Class Player Name? inheritance?807 Property name name? As String Type?808 Property points name? As Integer Type?809 Property cards name? As List(Of Card)Type?810 Property handTotal name? As Integer Type?811 Property softAce name? As Boolean Type?812 Property status name? As Status Type?813 Property hasTurn name? As Boolean Type?814 +Sub startTurn name?(parameter definitions parameter definitions?) ' procedure method 815 +If Me.status = Status.active condition? Then 816 Me.hasTurn variableName? = True value or expression? ' assignment 817 End If End Sub +Sub determineOutcomeAndUpdatePoints name?(dealer As Dealer parameter definitions?) ' procedure method 818 Dim playerOutcome name? = determinePlayerOutcome(dealer, Me)value or expression? ' variable definition 819 +If playerOutcome = Outcome.winDouble condition? Then 820 Me.changePointsBy procedureName?(2 arguments?) ' procedure call 821 dealer.changePointsBy procedureName?(-2 arguments?) ' procedure call 822 ElseIf playerOutcome = Outcome.win condition? Then 823 Me.changePointsBy procedureName?(1 arguments?) ' procedure call 824 dealer.changePointsBy procedureName?(-1 arguments?) ' procedure call 825 ElseIf playerOutcome = Outcome.lose condition? Then 826 Me.changePointsBy procedureName?(-1 arguments?) ' procedure call 827 dealer.changePointsBy procedureName?(1 arguments?) ' procedure call 828 End If End Sub +Sub evaluateStatus name?(newCard As Card parameter definitions?) ' procedure method 829 +If (Me.cardCount() = 2) And (Me.handTotal = 21)condition? Then 830 Me.status variableName? = Status.blackjack value or expression? ' assignment 831 ElseIf (Me.handTotal > 21) And (Me.softAce)condition? Then 832 Me.handTotal variableName? = Me.handTotal - 10 value or expression? ' assignment 833 Me.softAce variableName? = False value or expression? ' assignment 834 ElseIf Me.handTotal > 21 condition? Then 835 Me.status variableName? = Status.bust value or expression? ' assignment 836 ElseIf Me.handTotal = 21 condition? Then 837 Me.status variableName? = Status.standing value or expression? ' assignment 838 End If +If Me.status <> Status.active condition? Then 839 Me.hasTurn variableName? = False value or expression? ' assignment 840 End If End Sub +Sub stand name?(parameter definitions parameter definitions?) ' procedure method 841 Me.status variableName? = Status.standing value or expression? ' assignment 842 Me.hasTurn variableName? = False value or expression? ' assignment 843 End Sub +Sub draw name?(parameter definitions parameter definitions?) ' procedure method 844 Dim newCard name? = dealCard(random())value or expression? ' variable definition 845 Dim cards name? = Me.cards value or expression? ' variable definition 846 cards.append procedureName?(newCard arguments?) ' procedure call 847 +If newCard.rank.equals("A")condition? Then 848 Me.addAce procedureName?(arguments?) ' procedure call 849 Else 850 Me.handTotal variableName? = Me.handTotal + rankValue()(newCard.rank)value or expression? ' assignment 851 End If Me.evaluateStatus procedureName?(newCard arguments?) ' procedure call 852 End Sub +Sub addAce name?(parameter definitions parameter definitions?) ' procedure method 853 +If Me.softAce condition? Then 854 Me.handTotal variableName? = Me.handTotal + 1 value or expression? ' assignment 855 Else 856 Me.handTotal variableName? = Me.handTotal + 11 value or expression? ' assignment 857 Me.softAce variableName? = True value or expression? ' assignment 858 End If End Sub +Function cardCount name?(parameter definitions parameter definitions?) As Integer Type? 859 Return Me.cards.length()value or expression?860 End Function +Sub changePointsBy name?(amount As Integer parameter definitions?) ' procedure method 861 Me.points variableName? = Me.points + amount value or expression? ' assignment 862 End Sub MustOverride Sub newHand name?(parameter definitions parameter definitions?)863 +Protected Sub newHandHelper name?(parameter definitions parameter definitions?) ' private procedure method 864 Me.hasTurn variableName? = False value or expression? ' assignment 865 Me.softAce variableName? = False value or expression? ' assignment 866 Me.cards variableName? = New List(Of Card)()value or expression? ' assignment 867 Me.handTotal variableName? = 0 value or expression? ' assignment 868 Me.status variableName? = Status.active value or expression? ' assignment 869 Me.draw procedureName?(arguments?) ' procedure call 870 Me.draw procedureName?(arguments?) ' procedure call 871 End Sub MustOverride Function getMessage name?(parameter definitions parameter definitions?) As String Type?872 +Protected Function getMessageHelper name?(parameter definitions parameter definitions?) As String Type? 873 Dim msg name? = ""value or expression? ' variable definition 874 Dim status name? = Me.status value or expression? ' variable definition 875 +If Me.hasTurn condition? Then 876 msg variableName? = msg + " - PLAYING"value or expression? ' assignment 877 ElseIf status = Status.standing condition? Then 878 msg variableName? = msg + " - STANDING"value or expression? ' assignment 879 ElseIf status = Status.blackjack condition? Then 880 msg variableName? = msg + " - BLACKJACK"value or expression? ' assignment 881 ElseIf status = Status.bust condition? Then 882 msg variableName? = msg + " - BUST"value or expression? ' assignment 883 End If Return msg value or expression?884 End Function MustOverride Sub nextAction name?(dealerFaceCard As Card parameter definitions?)885 End Class
+abstract class Player Name? inheritance? {886 public String Type? name name?; // property 887 public int Type? points name?; // property 888 public List<Card>Type? cards name?; // property 889 public int Type? handTotal name?; // property 890 public boolean Type? softAce name?; // property 891 public Status Type? status name?; // property 892 public boolean Type? hasTurn name?; // property 893 +public void startTurn name?(parameter definitions parameter definitions?) { // procedure method 894 +if (this.status == Status.active condition?) { 895 this.hasTurn variableName? = true value or expression?; // assignment 896 } // end if } // end procedure method +public void determineOutcomeAndUpdatePoints name?(Dealer dealer parameter definitions?) { // procedure method 897 var playerOutcome name? = determinePlayerOutcome(dealer, this)value or expression?;898 +if (playerOutcome == Outcome.winDouble condition?) { 899 this.changePointsBy procedureName?(2 arguments?); // procedure call 900 dealer.changePointsBy procedureName?(-2 arguments?); // procedure call 901 } else if (playerOutcome == Outcome.win condition?) {902 this.changePointsBy procedureName?(1 arguments?); // procedure call 903 dealer.changePointsBy procedureName?(-1 arguments?); // procedure call 904 } else if (playerOutcome == Outcome.lose condition?) {905 this.changePointsBy procedureName?(-1 arguments?); // procedure call 906 dealer.changePointsBy procedureName?(1 arguments?); // procedure call 907 } // end if } // end procedure method +public void evaluateStatus name?(Card newCard parameter definitions?) { // procedure method 908 +if ((this.cardCount() == 2) && (this.handTotal == 21)condition?) { 909 this.status variableName? = Status.blackjack value or expression?; // assignment 910 } else if ((this.handTotal > 21) && (this.softAce)condition?) {911 this.handTotal variableName? = this.handTotal - 10 value or expression?; // assignment 912 this.softAce variableName? = false value or expression?; // assignment 913 } else if (this.handTotal > 21 condition?) {914 this.status variableName? = Status.bust value or expression?; // assignment 915 } else if (this.handTotal == 21 condition?) {916 this.status variableName? = Status.standing value or expression?; // assignment 917 } // end if +if (this.status != Status.active condition?) { 918 this.hasTurn variableName? = false value or expression?; // assignment 919 } // end if } // end procedure method +public void stand name?(parameter definitions parameter definitions?) { // procedure method 920 this.status variableName? = Status.standing value or expression?; // assignment 921 this.hasTurn variableName? = false value or expression?; // assignment 922 } // end procedure method +public void draw name?(parameter definitions parameter definitions?) { // procedure method 923 var newCard name? = dealCard(random())value or expression?;924 var cards name? = this.cards value or expression?;925 cards.append procedureName?(newCard arguments?); // procedure call 926 +if (newCard.rank.equals("A")condition?) { 927 this.addAce procedureName?(arguments?); // procedure call 928 } else {929 this.handTotal variableName? = this.handTotal + rankValue()[newCard.rank]value or expression?; // assignment 930 } // end if this.evaluateStatus procedureName?(newCard arguments?); // procedure call 931 } // end procedure method +public void addAce name?(parameter definitions parameter definitions?) { // procedure method 932 +if (this.softAce condition?) { 933 this.handTotal variableName? = this.handTotal + 1 value or expression?; // assignment 934 } else {935 this.handTotal variableName? = this.handTotal + 11 value or expression?; // assignment 936 this.softAce variableName? = true value or expression?; // assignment 937 } // end if } // end procedure method +public int Type? cardCount name?(parameter definitions parameter definitions?) { // function method 938 return this.cards.length()value or expression?;939 } // end function method +public void changePointsBy name?(int amount parameter definitions?) { // procedure method 940 this.points variableName? = this.points + amount value or expression?; // assignment 941 } // end procedure method abstract void newHand name?(parameter definitions parameter definitions?); // abstract procedure 942 +protected void newHandHelper name?(parameter definitions parameter definitions?) { // private procedure method 943 this.hasTurn variableName? = false value or expression?; // assignment 944 this.softAce variableName? = false value or expression?; // assignment 945 this.cards variableName? = new List<Card>()value or expression?; // assignment 946 this.handTotal variableName? = 0 value or expression?; // assignment 947 this.status variableName? = Status.active value or expression?; // assignment 948 this.draw procedureName?(arguments?); // procedure call 949 this.draw procedureName?(arguments?); // procedure call 950 } // end procedure method abstract String Type? getMessage name?(parameter definitions parameter definitions?); // abstract function 951 +protected String Type? getMessageHelper name?(parameter definitions parameter definitions?) { // private function method 952 var msg name? = ""value or expression?;953 var status name? = this.status value or expression?;954 +if (this.hasTurn condition?) { 955 msg variableName? = msg + " - PLAYING"value or expression?; // assignment 956 } else if (status == Status.standing condition?) {957 msg variableName? = msg + " - STANDING"value or expression?; // assignment 958 } else if (status == Status.blackjack condition?) {959 msg variableName? = msg + " - BLACKJACK"value or expression?; // assignment 960 } else if (status == Status.bust condition?) {961 msg variableName? = msg + " - BUST"value or expression?; // assignment 962 } // end if return msg value or expression?;963 } // end function method abstract void nextAction name?(Card dealerFaceCard parameter definitions?); // abstract procedure 964 } // end class

### What you need to know about an abstract class

- An abstract class is like a concrete class except that:
  - It may not be instantiated directly, and hence has no constructor.
  - A concrete class may inherit from it; this is specified in the concrete class, by entering the name of the desired abstract 'superclass' in the the field labelled inheritance. Note that when this has been entered the editor will add the syntax for inheritance appropriate to the language being used.
  - It may define concrete members (as found on concrete classes) and/or abstract members.
  - Any concrete class that inherits from an abstract class, must provide concrete implementations of all abstract members defined on its immediate superclass, and on any abstract classes defined in its hierarchy.
- An abstract class must be declared in the code above any class that inherits from it.
- Inheritance hierarchies must form a tree, that is you must avoid creating a circular dependency where, for example, type A inherits from type B, which inherits from type `CCCCC`, which inherits from type `AAAAA`.

### More advanced techniques

#### Delegation

If you want sub-classes to be able to define their own implementation of a common method, then that method should be made abstract. If it turns out that several of the sub-classes need the same, or very similar, implementations (and duplication of code is always to be avoided, according to the DRY principle - Don't Repeat Yourself) then you use the pattern of 'delegation'. This means defining the method as abstract, but also providing a private implementation (or part-implementation) with a slightly different name, which sub-classes may call from their own implementations. You can see an example of this in the Blackjack demo:

- The abstract class named `PlayerPlayerPlayerPlayerPlayer` defines `Code does not parse as Elan.Code does not parse as Elan.Code does not parse as Elan.Code does not parse as Elan.Code does not parse as Elan.`.
- It also defines a concrete procedure method named `newHandHelpernewHandHelpernewHandHelpernewHandHelpernewHandHelper`.
- The subclass `HumanPlayerHumanPlayerHumanPlayerHumanPlayerHumanPlayer` defines its implementation of newHand as just `call this.newHandHelperprocedureName?(arguments?)20self.newHandHelperprocedureName?(arguments?) # procedure call21this.newHandHelperprocedureName?(arguments?); // procedure call22Me.newHandHelperprocedureName?(arguments?) ' procedure call23this.newHandHelperprocedureName?(arguments?); // procedure call24`.
- The subclass `DealerDealerDealerDealerDealer` defines a more complex implementation of newHand with five instructions, but these include `call this.newHandHelperprocedureName?(arguments?)25self.newHandHelperprocedureName?(arguments?) # procedure call26this.newHandHelperprocedureName?(arguments?); // procedure call27Me.newHandHelperprocedureName?(arguments?) ' procedure call28this.newHandHelperprocedureName?(arguments?); // procedure call29` to do the common part of the task.

# Statement Instructions

Coding with Elan using the object-oriented paradigm offers the same statement instructions used in the procedural paradigm.

# Member instructions

Member instructions (also referred to simply as 'members') may be added only with a concrete class or abstract class. Hence, these method instructions may be created only when the paradigm is set to object-oriented (or functional - which includes all OOP capabilities).

## Constructor

### Examples of a constructor

From the Snake - object-oriented demo, where the `SquareSquareSquareSquareSquare` class defines this constructor:

+class Square Name? inheritance?965 +constructor(x as Int, y as Int parameter definitions?) 966 assign this.x variableName? to x value or expression?967 assign this.y variableName? to y value or expression?968 end constructor # other code not shown comment? +function toString name?(parameter definitions parameter definitions?) returns String Type? 969 return "{this.x}, {this.y}"value or expression?970 end function end class
+class Square Name? inheritance?: # concrete class 971 +def __init__(self: Square, x: int, y: int parameter definitions?) -> None: 972 self.x variableName? = x value or expression? # assignment 973 self.y variableName? = y value or expression? # assignment 974 # end constructor # other code not shown comment? +def toString name?(self: Square) -> str Type?: # function method 975 return "{this.x}, {this.y}"value or expression?976 # end function method # end class
+class Square Name? inheritance? {977 +public Square(int x, int y parameter definitions?) { 978 this.x variableName? = x value or expression?; // assignment 979 this.y variableName? = y value or expression?; // assignment 980 } // end constructor // other code not shown comment? +public string Type? toString name?(parameter definitions parameter definitions?) { // function method 981 return "{this.x}, {this.y}"value or expression?;982 } // end function method } // end class
+Class Square Name? inheritance?983 +Sub New(x As Integer, y As Integer parameter definitions?) 984 Me.x variableName? = x value or expression? ' assignment 985 Me.y variableName? = y value or expression? ' assignment 986 End Sub ' other code not shown comment? +Function toString name?(parameter definitions parameter definitions?) As String Type? 987 Return "{this.x}, {this.y}"value or expression?988 End Function End Class
+class Square Name? inheritance? {989 +public Square(int x, int y parameter definitions?) { 990 this.x variableName? = x value or expression?; // assignment 991 this.y variableName? = y value or expression?; // assignment 992 } // end constructor // other code not shown comment? +public String Type? toString name?(parameter definitions parameter definitions?) { // function method 993 return "{this.x}, {this.y}"value or expression?;994 } // end function method } // end class

which requires the programmer to provide values for parameters `xxxxx` and `yyyyy` when instantiating a `SquareSquareSquareSquareSquare`, and assigns these parameters to the corresponding properties of the object.

From the Blackjack demo, where the `GameGameGameGameGame` class defines this constructor:

+class Game Name? inheritance?995 +constructor(dealerStartPoints as Int parameter definitions?) 996 assign this.dealer variableName? to new Dealer(dealerStartPoints)value or expression?997 assign this.players variableName? to new List<of Player>()value or expression?998 assign this.message variableName? to ""value or expression?999 end constructor # other code not shown comment? +function toString name?(parameter definitions parameter definitions?) returns String Type? 1000 return "a Game"value or expression?1001 end function end class
+class Game Name? inheritance?: # concrete class 1002 +def __init__(self: Game, dealerStartPoints: int parameter definitions?) -> None: 1003 self.dealer variableName? = Dealer(dealerStartPoints)value or expression? # assignment 1004 self.players variableName? = list[Player]()value or expression? # assignment 1005 self.message variableName? = ""value or expression? # assignment 1006 # end constructor # other code not shown comment? +def toString name?(self: Game) -> str Type?: # function method 1007 return "a Game"value or expression?1008 # end function method # end class
+class Game Name? inheritance? {1009 +public Game(int dealerStartPoints parameter definitions?) { 1010 this.dealer variableName? = new Dealer(dealerStartPoints)value or expression?; // assignment 1011 this.players variableName? = new List<Player>()value or expression?; // assignment 1012 this.message variableName? = ""value or expression?; // assignment 1013 } // end constructor // other code not shown comment? +public string Type? toString name?(parameter definitions parameter definitions?) { // function method 1014 return "a Game"value or expression?;1015 } // end function method } // end class
+Class Game Name? inheritance?1016 +Sub New(dealerStartPoints As Integer parameter definitions?) 1017 Me.dealer variableName? = New Dealer(dealerStartPoints)value or expression? ' assignment 1018 Me.players variableName? = New List(Of Player)()value or expression? ' assignment 1019 Me.message variableName? = ""value or expression? ' assignment 1020 End Sub ' other code not shown comment? +Function toString name?(parameter definitions parameter definitions?) As String Type? 1021 Return "a Game"value or expression?1022 End Function End Class
+class Game Name? inheritance? {1023 +public Game(int dealerStartPoints parameter definitions?) { 1024 this.dealer variableName? = new Dealer(dealerStartPoints)value or expression?; // assignment 1025 this.players variableName? = new List<Player>()value or expression?; // assignment 1026 this.message variableName? = ""value or expression?; // assignment 1027 } // end constructor // other code not shown comment? +public String Type? toString name?(parameter definitions parameter definitions?) { // function method 1028 return "a Game"value or expression?;1029 } // end function method } // end class

Note that the single parameter defined in the instructor does not correspond directly to the any property defined on `GameGameGameGameGame`, but is used to create a new instance of `DealerDealerDealerDealerDealer` for its own `dealerdealerdealerdealerdealer` (association) property. Its `playerplayerplayerplayerplayer` property is a 'multiple association' and is initialised to a new (empty) list of type `PlayerPlayerPlayerPlayerPlayer`.

### What you need to know about a constructor

- A concrete class must have a constructor - so when a new concrete class is created, it includes a minimal default implementation.
- The purpose of the constructor is to initialise all properties (except, optionally, for properties of numeric or Boolean types - if you are happy for them to take the default values for those types).
- A property is initialised using a reassign instruction, prefixing the name of the propery as in this example – `assign this.xvariableName? to xvalue or expression?30self.xvariableName? = xvalue or expression? # assignment31this.xvariableName? = xvalue or expression?; // assignment32Me.xvariableName? = xvalue or expression? ' assignment33this.xvariableName? = xvalue or expression?; // assignment34` – the prefix means that you can have a parameter with the same name, with no risk of ambiguity.
- The constructor may make use of the object's function methods and/or global methods to calculate values to be assigned to its properties.
- However, a constructor may not call any procedure - internal or external - because constructing a new instance should have no side-effects.

## Property

### Examples of a property

From the Snake - object-oriented demo, where the `GameGameGameGameGame` class defines these properties:

Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.

### What you need to know about a property

- A property is a named value defined on a concrete or abstract class with a name conforming to the standard rules for an identifier.
- The type of a property, unlike a variable, is explicitly defined, as shown in the examples above. It may be a standard library type (including data structures), or the name of another used-defined class, or a data structure of another class type (see examples above).
- Every property must be initialsed within a constructor unless it is of a numeric or Boolean type - which have default values.
- A property is public by default, but may be specified as private (visible only to code inside the class) though the make private action on the context menu (or reverted to public with make public.
- The public properties of an instance may be read by code outside the class using dot-syntax, but may only be modified (from outside) via an appropriate procedure method.

### More advanced techniques

### Optional ('Maybe') associations

When a class property is optional, it is defined with the type `MaybeMaybeMaybeMaybeMaybe`.

Before reading the property's value, you must test if it has a value with function hasValue which returns a `BooleanboolboolBooleanboolean`. If `trueTruetrueTruetrue` is returned, then you retrieve the value with function getValue; if `falseFalsefalseFalsefalse` is returned, then it has no current value, and using getValue will give a runtime error.

To update the property's value, use function setValue. To restore it to having no value, use function clearValue.

Here a pupil (of class Pupil) that optionally has a tutor (of class Teacher):

+main 1033 variable tTom name? set to new Teacher()value or expression?1034 variable pPete name? set to new Pupil()value or expression?1035 +if pPete.tutor.hasValue()condition? then 1036 print(pPete.tutor arguments?)1037 end if print(p arguments?)1038 end main
+def main() -> None: 1039 tTom name? = Teacher()value or expression? # variable definition 1040 pPete name? = Pupil()value or expression? # variable definition 1041 +if pPete.tutor.hasValue()condition?: 1042 print(pPete.tutor arguments?)1043 # end if print(p arguments?)1044 # end main
+static void main() { 1045 var tTom name? = new Teacher()value or expression?;1046 var pPete name? = new Pupil()value or expression?;1047 +if (pPete.tutor.hasValue()condition?) { 1048 Console.WriteLine(pPete.tutor arguments?); // print statement 1049 } // end if Console.WriteLine(p arguments?); // print statement 1050 } // end main
+Sub main() 1051 Dim tTom name? = New Teacher()value or expression? ' variable definition 1052 Dim pPete name? = New Pupil()value or expression? ' variable definition 1053 +If pPete.tutor.hasValue()condition? Then 1054 Console.WriteLine(pPete.tutor arguments?) ' print statement 1055 End If Console.WriteLine(p arguments?) ' print statement 1056 End Sub
+static void main() { 1057 var tTom name? = new Teacher()value or expression?;1058 var pPete name? = new Pupil()value or expression?;1059 +if (pPete.tutor.hasValue()condition?) { 1060 System.out.println(pPete.tutor arguments?); // print statement 1061 } // end if System.out.println(p arguments?); // print statement 1062 } // end main

## Function method

### Examples of a function method

From the Roman Numerals Turing Machine demo, where the `Code does not parse as Elan.Code does not parse as Elan.Code does not parse as Elan.Code does not parse as Elan.Code does not parse as Elan.` class defines these two function methods:

+function isHalted name?(parameter definitions parameter definitions?) returns Boolean Type? 1063 return this.currentState.equals(this.haltState)value or expression?1064 end function
+def isHalted name?(parameter definitions parameter definitions?) -> bool Type?: # function 1065 return self.currentState.equals(self.haltState)value or expression?1066 # end function
+static bool Type? isHalted name?(parameter definitions parameter definitions?) { // function 1067 return this.currentState.equals(this.haltState)value or expression?;1068 } // end function
+Function isHalted name?(parameter definitions parameter definitions?) As Boolean Type? 1069 Return Me.currentState.equals(Me.haltState)value or expression?1070 End Function
+static boolean Type? isHalted name?(parameter definitions parameter definitions?) { // function 1071 return this.currentState.equals(this.haltState)value or expression?;1072 } // end function

### What you need to know about a function method

- A function method provides information based on the parameters specified in combination with the object's properties.
- A function method broadly follows the same rules as an ordinary (global) function - so it may not create any side effects nor.
- However, a function method may read, and hence depend upon, the properties of the object on which it is defined.
- A function method is public by default, but may be specified as private (visible only to code inside the class) though the make private action on the context menu (or reverted to public with make public).
- A function method may be called (within an expression) on an object in code outside the class using dot-syntax on the variable holding the instance.
- A function method may be invoked from within another method inside the class using, for example `this.methodName()self.methodName()this.methodName()Me.methodName()this.methodName()`.

## Procedure method

### Examples of a procedure method

From the Roman Numerals Turing Machine demo, where the `Code does not parse as Elan.Code does not parse as Elan.Code does not parse as Elan.Code does not parse as Elan.Code does not parse as Elan.` defines these procedure methods (among others):

+procedure setTape name?(tape as String parameter definitions?) 1073 assign this.tape variableName? to tape value or expression?1074 end procedure
+def setTape name?(tape: str parameter definitions?) -> None: # procedure 1075 self.tape variableName? = tape value or expression? # assignment 1076 # end procedure
+static void setTape name?(string tape parameter definitions?) { // procedure 1077 this.tape variableName? = tape value or expression?; // assignment 1078 } // end procedure
+Sub setTape name?(tape As String parameter definitions?) ' procedure 1079 Me.tape variableName? = tape value or expression? ' assignment 1080 End Sub
+static void setTape name?(String tape parameter definitions?) { // procedure 1081 this.tape variableName? = tape value or expression?; // assignment 1082 } // end procedure

This is the simplest form of a procedure method, which allows the `tapetapetapetapetape` property (a string) to be set to a new value by code outside the class.

+procedure singleStep name?(parameter definitions parameter definitions?) 1083 variable rule name? set to this.findMatchingRule()value or expression?1084 call this.execute procedureName?(rule arguments?)1085 end procedure
+def singleStep name?(parameter definitions parameter definitions?) -> None: # procedure 1086 rule name? = self.findMatchingRule()value or expression? # variable definition 1087 self.execute procedureName?(rule arguments?) # procedure call 1088 # end procedure
+static void singleStep name?(parameter definitions parameter definitions?) { // procedure 1089 var rule name? = this.findMatchingRule()value or expression?;1090 this.execute procedureName?(rule arguments?); // procedure call 1091 } // end procedure
+Sub singleStep name?(parameter definitions parameter definitions?) ' procedure 1092 Dim rule name? = Me.findMatchingRule()value or expression? ' variable definition 1093 Me.execute procedureName?(rule arguments?) ' procedure call 1094 End Sub
+static void singleStep name?(parameter definitions parameter definitions?) { // procedure 1095 var rule name? = this.findMatchingRule()value or expression?;1096 this.execute procedureName?(rule arguments?); // procedure call 1097 } // end procedure

This method made use of a function method on the same class - findMatchingRule() - and then calls another procedure on the same instance - execute - passing it the found `rulerulerulerulerule`.

### What you need to know about a procedure method

- A procedure method changes the state of the object, and/or interacts with the system
- A procedure method broadly follows the same rules as an ordinary (global) function - so it may not create any side effects nor.
- However, a procedure method may read, and hence depend upon, the properties of the object on which it is defined.
- A procedure method is public by default, but may be specified as private (visible only to code inside the class) though the make private action on the context menu (or reverted to public with make public).
- A procedure method may be called (using a procedure call/b>) on an object in code outside the class using dot-syntax on the variable holding the instance.
- A procedure method may be called from within another method inside the class using, for example `call this.methodNameprocedureName?(arguments?)35self.methodNameprocedureName?(arguments?) # procedure call36this.methodNameprocedureName?(arguments?); // procedure call37Me.methodNameprocedureName?(arguments?) ' procedure call38this.methodNameprocedureName?(arguments?); // procedure call39`.

## Abstract function

### Examples of an abstract function

From the Blackjack demo, where the abstract class `PlayerPlayerPlayerPlayerPlayer` defines this abstract function:

Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.

which is implemented (as a concrete function method) by the subclasses, including on `DealerDealerDealerDealerDealer`:

+function getMessage name?(parameter definitions parameter definitions?) returns String Type? 1098 variable msg name? set to ""value or expression?1099 +if this.hasPlayed condition? then 1100 assign msg variableName? to this.getMessageHelper() + $" - hand total: {this.handTotal}"value or expression?1101 end if return msg value or expression?1102 end function
+def getMessage name?(parameter definitions parameter definitions?) -> str Type?: # function 1103 msg name? = ""value or expression? # variable definition 1104 +if self.hasPlayed condition?: 1105 msg variableName? = self.getMessageHelper() + f" - hand total: {self.handTotal}"value or expression? # assignment 1106 # end if return msg value or expression?1107 # end function
+static string Type? getMessage name?(parameter definitions parameter definitions?) { // function 1108 var msg name? = ""value or expression?;1109 +if (this.hasPlayed condition?) { 1110 msg variableName? = this.getMessageHelper() + $" - hand total: {this.handTotal}"value or expression?; // assignment 1111 } // end if return msg value or expression?;1112 } // end function
+Function getMessage name?(parameter definitions parameter definitions?) As String Type? 1113 Dim msg name? = ""value or expression? ' variable definition 1114 +If Me.hasPlayed condition? Then 1115 msg variableName? = Me.getMessageHelper() + $" - hand total: {Me.handTotal}"value or expression? ' assignment 1116 End If Return msg value or expression?1117 End Function
+static String Type? getMessage name?(parameter definitions parameter definitions?) { // function 1118 var msg name? = ""value or expression?;1119 +if (this.hasPlayed condition?) { 1120 msg variableName? = this.getMessageHelper() + String.format(" - hand total: %", this.handTotal)value or expression?; // assignment 1121 } // end if return msg value or expression?;1122 } // end function

which makes use of a method getMessageHelper() that is defined as (private) concrete function method on the superclass (`PlayerPlayerPlayerPlayerPlayer`).

### What you need to know about an abstract function

- An abstract function method may be defined only on an abstract class .
- Any concrete subclass must then implement a concrete (regular) function to match.

## Abstract procedure

### Examples of an abstract procedure

From the Blackjack demo, where the abstract class `PlayerPlayerPlayerPlayerPlayer` defines this abstract function:

Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.
Code does not parse as Elan.

which is implemented (as a concrete function method) by the subclass `DealerDealerDealerDealerDealer` using simple logic to implement the standard rules that a Blackjack dealer must always follow:

+procedure nextAction name?(faceCard as Card parameter definitions?) 1123 +if this.handTotal < 17 condition? then 1124 call this.draw procedureName?(arguments?)1125 else 1126 call this.stand procedureName?(arguments?)1127 end if end procedure
+def nextAction name?(faceCard: Card parameter definitions?) -> None: # procedure 1128 +if self.handTotal < 17 condition?: 1129 self.draw procedureName?(arguments?) # procedure call 1130 else:1131 self.stand procedureName?(arguments?) # procedure call 1132 # end if # end procedure
+static void nextAction name?(Card faceCard parameter definitions?) { // procedure 1133 +if (this.handTotal < 17 condition?) { 1134 this.draw procedureName?(arguments?); // procedure call 1135 } else {1136 this.stand procedureName?(arguments?); // procedure call 1137 } // end if } // end procedure
+Sub nextAction name?(faceCard As Card parameter definitions?) ' procedure 1138 +If Me.handTotal < 17 condition? Then 1139 Me.draw procedureName?(arguments?) ' procedure call 1140 Else 1141 Me.stand procedureName?(arguments?) ' procedure call 1142 End If End Sub
+static void nextAction name?(Card faceCard parameter definitions?) { // procedure 1143 +if (this.handTotal < 17 condition?) { 1144 this.draw procedureName?(arguments?); // procedure call 1145 } else {1146 this.stand procedureName?(arguments?); // procedure call 1147 } // end if } // end procedure

and on the subclass `HumanPlayerHumanPlayerHumanPlayerHumanPlayerHumanPlayer` by code that uses input/output methods to obtain the next action from the user:

+procedure nextAction name?(dealerFaceCard as Card parameter definitions?) 1148 variable key name? set to ""value or expression?1149 call clearKeyBuffer procedureName?(arguments?)1150 +while key.equals("")condition? 1151 assign key variableName? to waitForKey()value or expression?1152 +if key.equals("d")condition? then 1153 call this.draw procedureName?(arguments?)1154 elif key.equals("s")condition? then 1155 call this.stand procedureName?(arguments?)1156 else 1157 assign key variableName? to ""value or expression?1158 end if end while end procedure
+def nextAction name?(dealerFaceCard: Card parameter definitions?) -> None: # procedure 1159 key name? = ""value or expression? # variable definition 1160 clearKeyBuffer procedureName?(arguments?) # procedure call 1161 +while key.equals("")condition?: 1162 key variableName? = waitForKey()value or expression? # assignment 1163 +if key.equals("d")condition?: 1164 self.draw procedureName?(arguments?) # procedure call 1165 elif key.equals("s")condition?: # else if 1166 self.stand procedureName?(arguments?) # procedure call 1167 else:1168 key variableName? = ""value or expression? # assignment 1169 # end if # end while # end procedure
+static void nextAction name?(Card dealerFaceCard parameter definitions?) { // procedure 1170 var key name? = ""value or expression?;1171 clearKeyBuffer procedureName?(arguments?); // procedure call 1172 +while (key.equals("")condition?) { 1173 key variableName? = waitForKey()value or expression?; // assignment 1174 +if (key.equals("d")condition?) { 1175 this.draw procedureName?(arguments?); // procedure call 1176 } else if (key.equals("s")condition?) {1177 this.stand procedureName?(arguments?); // procedure call 1178 } else {1179 key variableName? = ""value or expression?; // assignment 1180 } // end if } // end while } // end procedure
+Sub nextAction name?(dealerFaceCard As Card parameter definitions?) ' procedure 1181 Dim key name? = ""value or expression? ' variable definition 1182 clearKeyBuffer procedureName?(arguments?) ' procedure call 1183 +While key.equals("")condition? 1184 key variableName? = waitForKey()value or expression? ' assignment 1185 +If key.equals("d")condition? Then 1186 Me.draw procedureName?(arguments?) ' procedure call 1187 ElseIf key.equals("s")condition? Then 1188 Me.stand procedureName?(arguments?) ' procedure call 1189 Else 1190 key variableName? = ""value or expression? ' assignment 1191 End If End While End Sub
+static void nextAction name?(Card dealerFaceCard parameter definitions?) { // procedure 1192 var key name? = ""value or expression?;1193 clearKeyBuffer procedureName?(arguments?); // procedure call 1194 +while (key.equals("")condition?) { 1195 key variableName? = waitForKey()value or expression?; // assignment 1196 +if (key.equals("d")condition?) { 1197 this.draw procedureName?(arguments?); // procedure call 1198 } else if (key.equals("s")condition?) {1199 this.stand procedureName?(arguments?); // procedure call 1200 } else {1201 key variableName? = ""value or expression?; // assignment 1202 } // end if } // end while } // end procedure

### What you need to know about an abstract procedure

- An abstract abstract_procedure method may be defined only on an abstract class .
- Any concrete subclass must then implement a concrete (regular) function to match.

## Comment

See Comments

Elan Language Reference go to the top 