.. @raise litre.TestsAreMissing

=============================
Stored and Computed Variables
=============================

.. warning:: This document has not been updated since the initial design in
  Swift 1.0.


Variables are declared using the ``var`` keyword. These declarations are valid
at the top level, within types, and within code bodies, and are respectively
known as *global variables,* *member variables,* and *local variables.*
Member variables are commonly referred to as *properties.* 

Every variable declaration can be classified as either *stored* or *computed.*
Member variables inherited from a superclass obey slightly different rules.

.. contents:: :local:


Stored Variables
================

The simplest form of a variable declaration provides only a type::

  var count : Int

This form of ``var`` declares a *stored variable.* Stored variables cause
storage to be allocated in their containing context:

- a new global symbol for a global variable
- a slot in an object for a member variable
- space on the stack for a local variable

(Note that this storage may still be optimized away if determined unnecessary.)

Stored variables must be initialized before use. As such, an initial value can
be provided at the declaration site. This is mandatory for global variables,
since it cannot be proven who accesses the variable first. ::

  var count : Int = 10

If the type of the variable can be inferred from the initial value expression,
it may be omitted in the declaration::

  var count = 10

Variables formed during pattern matching are also considered stored
variables. ::

  switch optVal {
  case .Some(var actualVal):
    // do something
  case .None:
    // do something else
  }


Computed Variables
==================

A *computed variable* behaves syntactically like a variable, but does not
actually require storage. Instead, accesses to the variable go through
"accessors" known as the *getter* and the *setter.* Thus, a computed variable
is declared as a variable with a custom getter::

  struct Rect {
    // Stored member variables
    var x, y, width, height : Int

    // A computed member variable
    var maxX : Int {
      get {
        return x + width
      }
      set(newMax) {
        x = newMax - width
      }
    }

  // myRect.maxX = 40

In this example, no storage is provided for ``maxX``.

If the setter's argument is omitted, it is assumed to be named ``value``::

    var maxY : Int {
      get {
        return y + height
      }
      set {
        y = value - height
      }
    }

Finally, if a computed variable has a getter but no setter, it becomes a
*read-only variable.*  In this case the ``get`` label may be omitted.
Attempting to set a read-only variable is a compile-time error::

    var area : Int {
      return self.width * self.height
    }
  }

Note that because this is a member variable, the implicit parameter ``self`` is
available for use within the accessors.

It is illegal for a variable to have a setter but no getter.


Observing Accessors
===================

Occasionally it is useful to provide custom behavior when changing a variable's
value that goes beyond simply modifying the underlying storage. One way to do
this is to pair a stored variable with a computed variable::

  var _backgroundColor : Color
  var backgroundColor : Color {
    get {
      return _backgroundColor
    }
    set {
      _backgroundColor = value
      refresh()
    }
  }

However, this contains a fair amount of boilerplate. For cases where a stored
property provides the correct storage semantics, you can add custom behavior
before or after the underlying assignment using "observing accessors"
``willSet`` and ``didSet``::

  var backgroundColor : Color {
    didSet {
      refresh()
    }
  }

  var currentURL : URL {
    willSet(newValue) {
      if newValue != currentURL {
        cancelCurrentRequest()
      }
    }
    didSet {
      sendNewRequest(currentURL)
    }
  }

A stored property may have either observing accessor, or both. Like ``set``,
the argument for ``willSet`` may be omitted, in which case it is provided as
"value"::

  var accountName : String {
    willSet {
      assert(value != "root")
    }
  }

Observing accessors provide the same behavior as the two-variable example, with
two important exceptions:

- A variable with observing accessors is still a stored variable, which means
  it must still be initialized before use. Initialization does not run the
  code in the observing accessors.
- All assignments to the variable will trigger the observing accessors with
  the following exceptions: assignments in the init and destructor function for
  the enclosing type, and those from within the accessors themselves.  In this
  context, assignments directly store to the underlying storage.

Computed properties may not have observing accessors. That is, a property may
have a custom getter or observing accessors, but not both.


Overriding Read-Only Variables
==============================

If a member variable within a class is a read-only computed variable, it may
be overridden by subclasses. In this case, the subclass may choose to replace
that computed variable with a stored variable by declaring the stored variable
in the usual way::

  class Base {
    var color : Color {
      return .Black
    }
  }
  
  class Colorful : Base {
    var color : Color
  }

  var object = Colorful(.Red)
  object.color = .Blue

The new stored variable may have observing accessors::

  class MemoryColorful : Base {
    var oldColors : Array<Color> = []
  
    var color : Color {
      willSet {
        oldColors.append(color)
      }
    }
  }

A computed variable may also be overridden with another computed variable::

  class MaybeColorful : Base {
    var color : Color {
      get {
        if randomBooleanValue() {
          return .Green
        } else {
          return super.color
        }
      }
      set {
        print("Sorry, we choose our own colors here.")
      }
    }
  }


Overriding Read-Write Variables
===============================

If a member variable within a class as a read-write variable, it is not
generally possible to know if it is a computed variable or stored variable.
A subclass may override the superclass's variable with a new computed variable::

  class ColorBase {
    var color : Color {
      didSet {
        print("I've been painted \(color)!")
      }
    }
  }
  
  class BrightlyColored : ColorBase {
    var color : Color {
      get {
        return super.color
      }
      set(newColor) {
        // Prefer whichever color is brighter.
        if newColor.luminance > super.color.luminance {
          super.color = newColor
        } else {
          // Keep the old color.
        }
      }
    }
  }

In this case, because the superclass's ``didSet`` is part of the generated
setter, it is only called when the subclass actually invokes setter through
its superclass. On the ``else`` branch, the superclass's ``didSet`` is skipped.

A subclass may also use observing accessors to add behavior to an inherited
member variable::

  class TrackingColored : ColorBase {
    var prevColor : Color?
    
    var color : Color {
      willSet {
        prevColor = color
      }
    }
  }

In this case, the ``willSet`` accessor in the subclass is called first, then
the setter for ``color`` in the superclass. Critically, this is *not* declaring
a new stored variable, and the subclass will *not* need to initialize ``color``
as a separate member variable.

Because observing accessors add behavior to an inherited member variable, a
superclass's variable may not be overridden with a new stored variable, even
if no observing accessors are specified. In the rare case where this is
desired, the two-variable pattern shown above__ can be used.

__ `Observing Accessors`_

