How To Make A Class Hierarchy
Print Hello World
Write Basic Syntax
Use Properties
Make An If Else Ladder
Make A Branch Statement
Declare Inits
Use Lists
Use Arrays
Make A Class Hierarchy
Use Nil And Nilable Types
Use Dynamic Typing
Declare Variable Number Of Args
Read And Write Files
Check Inheritance And Implementation
Customize Object Equality
Pass References To Methods
Translate Pseudo Code To Cobra 1
Translate Pseudo Code To Cobra 2
Implement IEnumerable 1
Implement IEnumerable 2
Iterate Through Recursive Data With Yield
Make A Collection Class
Declare Contracts
Threads
Win Forms
WPF
GTK
Qyoto
Access MySQL
XNA
Open TK
 
"""
MakeAClassHierarchy.cobra

This HowTo shows the syntax for classes, inheritance, initializers, properties,
defining toString, unit tests and so forth.

The class hierarchy is:

Object
    Vehicle
        Aircraft
            Plane
        Train
        Automobile
"""


enum Medium
    """
    Defines the various mediums that a vehicle can travel through.
    """
    belowWater
    aboveWater
    land
    air
    space


class Vehicle

    test
        v = Vehicle()
        assert not v.isMoving
        assert not v.hasMoved
        assert v.serialNum > 0

        v.startMoving
        assert v.isMoving
        assert not v.hasMoved  # because no miles accumulated

        v.move(5)
        assert v.isMoving
        assert v.hasMoved
        assert v.numMiles == 5

        v.move(3)
        assert v.numMiles == 8

        v.stopMoving
        assert not v.isMoving
        assert v.hasMoved

        w = Vehicle()
        assert v.serialNum <> w.serialNum


    shared
        var __nextSerialNum = 1001

    cue init
        base.init
        _serialNum = __nextSerialNum
        __nextSerialNum += 1

    get serialNum from var as int
        # `get` defines a read-only property.
        # `from var` is a shortcut syntax to cover
        # the variable with the matching name.

    get hasMoved as bool
        return _numMiles > 0

    get isMoving from var as bool

    get numMiles from var as number

    def startMoving
        assert not _isMoving, 'Already moving.'
        _isMoving = true

    def move(distance as decimal)
        assert _isMoving, 'Invoke startMoving first.'
        assert distance > 0
        _numMiles += distance

    def stopMoving
        assert _isMoving, 'Not moving.'
        _isMoving = false

    def canTravelIn(medium as Medium) as bool
        """
        Returns true if the given medium is the primary medium that the vehicle
        normally travels through.
        """
        return false

    def toString as String is override
        test
            v = Vehicle()
            sn = v.serialNum
            assert v.toString == 'Vehicle([sn])'
        body
            sb = StringBuilder()
            sb.append('[.typeOf.name]([_serialNum]')  # example: 'Foo(1001)'
            .buildString(sb)  # so subclasses can add their fields
            sb.append(')')
            return sb.toString

    def buildString(sb as StringBuilder) is protected
        """
        Invoked by `toString` so that subclasses can add their information.
        Subclasses should normally invoke base.
        """
        pass


class Aircraft inherits Vehicle

    def canTravelIn(medium as Medium) as bool is override
        return medium == Medium.air


class Plane inherits Aircraft

    pass


class Train inherits Vehicle

    cue init(numUnits as int)
        require numUnits > 0  # see "Declare Contracts" How To
        base.init
        _numUnits = numUnits

    get numUnits from var as int
        """
        The number of locomotives and railroad cars in the train.
        """

    def canTravelIn(medium as Medium) as bool is override
        return medium == Medium.land

    def buildString(sb as StringBuilder) is protected, override
        base.buildString(sb)
        sb.append(', [_numUnits] units')


class Automobile inherits Vehicle

    def canTravelIn(medium as Medium) as bool is override
        return medium == Medium.land


class Program

    def main
        # create some vehicles
        p = Plane()
        t = Train(5)
        a = Automobile()

        vehicles = [p, t, a]  # a list

        for v in vehicles
            assert v.serialNum > 0
            print v