= Class Definitions = A class provides the definition for the type of an object and the variables, properties, events, and methods that the class comprises.[[BR]] In addition it may declare tests to exercise the class and contracts or constraints the class must conform to to ensure continuing validity. Classes are declared using the '''class''' keyword followed by the name of the class.[[BR]] The classname must start with an uppercase letter. [[BR]] The class may have any of the usual [wiki:AccessModifiers access modifiers]. [[BR]] The Superclass inheritance and interface conformance are indicated with the '''inherits''' and '''implements''' keywords. === Class Grammar === {{{ class [is ] [has ] [where must be ] [inherits ] [implements [, ]...] [] [ [] [] [ [] [] [] [] [] ]... # empty (placeholder) class class [is ] [has ] [where must be ] [inherits ] [implements [, ]...] [] pass }}} == Instance and Class Variables == Instance and Class variables are declared within the class using keyword '''var''' followed by the var name.[[BR]] Like local variables they may be explicitly typed ( {{{ as }}} ) and if not are defaulted to type '''dynamic'''. An initial value may be specified (if not the var gets its types 'empty' value ( 0, "" or nil)[[BR]] (Idiomatically its usually preferable to explicitly initialise the var and not explicitly specify the Type). [wiki:AccessModifiers AccessModifiers] usually specifying visibility can also be given. === Instance and Class variable definition Grammar === {{{ var [as ] [= ] [is [has ] ] [] var [as ] [= ] [is ] [has ] [] }}} e.g. {{{ #!cobra var x as String var _y as int var _ya as int = 47 var z as int is private var t as int = 99 is protected, shared """t is a Temporary backup value""" }}} All class and instance variable names must start with a lowerCase Letter[[BR]] If the name is prefixed with an '''_''' (single underscore) its accessType defaults to '''protected''' and it is directly accessible from within the class method code.[[BR]] If the name is prefixed with an '''_ _''' (double underscore) its accessType defaults to '''private''' and it is directly accessible from within the class method code.[[BR]] Without that prefix on the name the variables accessType is '''public''' (by default) and it must be accessed from within method code by prefixing the name with either '''this.''' or just '''.''' .[[BR]] In either case the default [wiki:AccessModifiers access ] setting can be adjusted with an access modifier clause.[[BR]] Class (or static) variables are specified with the access modifier '''shared''' as in {{{ is shared }}}[[BR]] e.g. {{{ #!cobra var _x = 100 # default protected def tryx( opnd as int) as int return _x + opnd var __x = 200 # default private def tryPrivx( opnd as int) as int return __x + opnd var y is protected # default public, explicit access modifier overrides setting to protected def tryy( opnd as int) as int return .y + opnd var statX as int = 45 is shared def x print .statX }}} == Properties == ''This discussion is somewhat simplified for clarity.[[BR]] Please see [wiki:Property Properties]'' Properties are members that provide a flexible mechanism to read, write, or compute the values of private fields. [[BR]] They are used as if they are public data members, but are actually implemented via special methods called accessors. There are 3 keywords for defining a property:[[BR]] '''get''' defines a readOnly property ( Can access the properties value but cant change it). [[BR]] '''set''' defines a writeOnly property (Can write to the property but cant read it)[[BR]] '''pro''' defines a readable and writable property. If a property accessor merely reflects a protected or private backing variable (field) you can[[BR]] use a clause beginning with keyword '''from'''. * '''from var''' [[BR]] {{{ pro from var }}} or {{{get from var}}} or {{{ set from var}}}[[BR]] The property will get or set its value unchanged from a backing variable named to the property name with a single underscore prepended to it. * If there is no backing variable but there is an assignment to the property or a type declaration on the property the backing variable will be implicitly created for you. * ''' from '''[[BR]] Otherwise the word following the '''from''' must be the name of an existing backing store variable. Finally if an accessor needs to translate, filter or modifies in some way a backing variable or computes a value[[BR]] there is a longer syntax variant where either of both the get and set accessors can be specified and a block of code[[BR]] provided to store (setter) or generate (getter) the property value. === (Simplified) Properties Grammar === {{{ get [ as ] [from {var, } [= ] ] [] set [ as ] [from {var, } [= ] ] [] pro [ as ] [from {var, } [= ] ] [] # full accessor variant, one or both of 'get' and 'set blocks must be present. pro get [...] return set [...] # assign or otherwise do something with implicit arg "value" (passed in) }}} === Property Example === {{{ #!cobra var _x = 47 pro x from var # property x uses backing var _x # above same as #pro x from _x }}} Can do all of the above in one line like {{{ #!cobra pro x = 47 # or pro x as int = 47 }}} Above is equivalent to fully specified accessor form {{{ #!cobra var _x = 47 pro get return _x set _x = value }}} == Methods == A method is a code block that contains a series of statements. [[BR]] A program causes the statements to be executed by calling the method and specifying any required method arguments. Methods are defined using the keyword '''def'''. If not specified the returnType is void ( i.e nothing returned) and the [wiki:AccessModifiers access modifiers] are '''public, virtual'''[[BR]] Like variables if the name is prefixed with an '''_''' its access modifier defaults to ''protected, virtual'' and it is directly accessible from within the class method code.[[BR]] If the name is prefixed with an '''_ _''' (double underscore) its access modifier defaults to ''private',virtual' and it is directly accessible from within the class method code.[[BR]] Without those prefixes on the name of the methods the accessType is ''public, virtual'' and it must be accessed from within method code by prefixing the name with either '''this.''' or just '''.''' .[[BR]] === Method Grammar === {{{ def [as ] [is ] [has ] [] def () [as ] [is ] [has ] [] }}} The initializer or constructor method of a class is a special method called '''init''' which is implicitly called when a class instance is constructed. Its responsible for setting the contents of a class instance to an initial state. It doesnt return any value and is not inherited (i.e baseclass initialization must be done with an explicit call to a baseclass constructor). If an init method is not specified the compiler runtime generates a noArg constructor that does nothing. Because this method is 'special' it is declared using '''cue''' rather than '''def'''. See [wiki:Cues cues] Constructor chaining must be done explicitly to another constructor in the same class (usually with a different number or Type of args) or to a Superclass constructor (using '''base.init''') - this call must be the first executable line in the init method. ==== Method Parameter List ==== A parameter list is a comma separated list of name (and optionally type and parameter description modifier) specifications {{{ [as [] ] [, ...] }}} is optional and may be '''vari''' and/or a parameter direction indicator '''out''' or '''inout''' ( default if unspecified is '''in''')[[BR]] '''vari''' indicates the parameter name is a placeholder for a variable length arglist. Within the method this may be unpacked/accessed as a list.[[BR]] '''in''' (implicit) Args are only passed into the method. Any changes made to the argument inside the method are not visible outside the method (pass-by-value)[[BR]] '''out''' the arg is returned from the method [[BR]] '''inout''' argument is both passed into the method and (any possibly changed) value is also returned from the method (pass-by-reference)[[BR]] If is unspecified it is treated as dynamic?[[BR]] e.g. {{{ #!cobra def meth( a, b is String, c is out String) c = b + "_meth" def sum(a as vari int) as int sum = 0 for i in a sum += i return sum }}} meth takes 3 args , the first and second are inward only and are dynamic and a string respectively, the third is only returned from the method as a string.[[BR]] sum takes a variable number of integer args. == TBD == ''Generics'' ''accessing baseclass methods'' == Example == {{{ #!cobra class SimplestClass pass class VeryMinimal """ Docstring for class """ cue init base.init # Above is equivalent to no initialiser at all # .... rest of initialiser code def aMethod print 'in aMethod of class [this]' # more method code }}} A more extended example. {{{ #!cobra #Interfaces interface Audible def makesNoise as String interface Mateable pro mateName as String interface Breedable inherits Mateable pro childName as String # class declaration - note indentation class Bovidae def diet as String return 'Herbivorous Cud Chewing' def numHooves as int return 4 class Sheep is public, nonvirtual # public is default anyway inherits Bovidae # Superclass implements Audible, Breedable var _lifeSpan as int = 8 is shared # years average # or var lifeSpan as int private shared var _age as int =1 var liveWeight as int is private var _isAlive as bool #shared #_lifespan = 8 cue init _age = 1 .liveWeight = 2 _isAlive = true def makesNoise as String return 'Baaaaa' pro mateName as String get return 'Ram' set pass pro childName as String get return 'lamb' set pass def age(byNYears as int) _age += byNYears if _age > _lifeSpan _isAlive = false def gainWgt(wgt as int) .liveWeight += wgt def toString as String is new return 'Sheep:age=[_age], weight=[.liveWeight], living=[_isAlive]' def main is shared s = Sheep() print 's=[s]' s.age(1) }}}