Wiki
Version 17 (modified by Charles, 4 years ago)

--

Mixins

Introduction

Provide a non inheritance based capability for providing shared/common characteristics and behaviour.

Basically, selected traits or characteristics and behaviours are described in a special Type called a 'mixin' (analogous to an interface),
these can then be specified on a class and are injected into that class to provide those traits on that class.

Mixin behaviours can be specified using object:

  • vars
  • properties
  • methods

They do not support constructors

(For more see the  Forum discussion thread).

Compared to Extensions

  • Extensions enable adding methods to existing classes whereas mixins only augment types that you declare.
  • Mixins can add state (object variables declared with var) whereas extensions cannot.
  • Mixins can add properties whereas extensions cannot.
  • Mixin members will be found at run-time via reflection whereas extension members will not.
  • Mixins create new types. From a VirtualMachine perspective, they are seen as interfaces (since the popular VMs don't support mixins).
  • Mixins cannot be used from a binary library. The source must be included for the compiler.

In summary, mixins are more about implementing shared capabilities among the (non common ancestor) types you are declaring.
Extensions are about adding convenience methods to existing types (regardless of who declared them).

Restrictions

As we gain more experience with using mixins, and as the implementation of mixins matures, some of the following restrictions are likely to be removed:

  • Mixins cannot declare initializers.
  • Mixins cannot inherit from other types.
  • Mixins cannot implement interfaces.
  • Mixins cannot add other mixins.
  • Mixins cannot declare generic parameters (see  forum's thread) nor being generic themselves (see  forum's thread).
  • Mixins cannot add invariants.
  • Two or more mixins added to a single type cannot have collision in their member names.
  • Mixins cannot make use of methods/members already present in the the target type. To support this, a mixin declaration would need to be able to declare the signatures of such members.

Example


# The behaviour desired - a name property
mixin Named
    var _name as String?
    pro name as String
        get
        return _name ? ''
    set
        _name = value

    get capName
        return _name[:1].toUpper + _name[1:]
    
    
# the (otherwise empty) class with mixin added
class A adds Named  
    pass

class B adds Named
    pass

class P
    def main is shared
        a = A()
        assert a inherits Named
        assert a.name == ''
        a.name = 'arosebyanyothername'
        assert a.name == 'arosebyanyothername'
        assert a.capName == 'Arosebyanyothername'

See also