Chapter 15. Type inheritance

Description

Type inheritance is the ability of one type to have (or to inherit) all the features (i.e. attributes, commands and events) of one or more other types.

If type T2 has all the features of type T1 then:

  • the inheritance can be graphically represented as follows:

    Figure 15.1. T2 inherits from T1

    T2 inherits from T1

  • the terminology we use is:

    • T2 inherits from T1
    • T2 is a child type of T1
    • T1 is a parent type of T2

  • the syntax for T1 and T2 in Obix source code is:

    type T1
    
       // definition of attributes, commands and events
    
    end
    type T2
    
       inherit T1 end
    
    end

Rules

Type inheritance is governed by the following rules:

  1. A child type can optionally define its own additional features which are not defined in its parent type(s).

    Figure 15.2. Additional features in a child type

    Additional features in a child type

    Terminology:

    - in type T2, f1 and f2 are features inherited from type T1. f1 and f2 both exist in T2 and in T1.

    - f3 is an own feature of type T2, also called an uninherited feature of type T2. f3 exists in T2, but not in T1.

    Example:

    In the following source code example, type book inherits 3 attributes and 1 command from type product and adds one more uninherited feature, namely attribute author.

    type product
    
       attribute identifier type:positive32 end
       attribute name type:string end
       attribute price_in_cents type:positive32 end
       
       command convert_to_XML
          out result type:string end
       end
    
    end
    type book 
    
       inherit product end
    
       attribute author type:string end
    
    end
  2. A type can inherit from several other types.

    Figure 15.3. Multiple type inheritance

    Multiple type inheritance

    [Note]Note
    There is no limit as to the number of types a given type can inherit from. However, directly inheriting from more than about 7 types appears very rarely in practice and might be a sign of design that needs to be improved.

    Terminology:

    - When a type inherits from just one other type we speak about single type inheritance.

    - When a type inherits from more than one other type we speak about multiple type inheritance.

    Example:

    In the following code type fruit is an example of multiple type inheritance, because fruit inherits from product and expirable.

    type product
    
       attribute identifier type:positive32 end
       attribute name type:string end
       attribute price_in_cents type:positive32 end
       
       command convert_to_XML
          out result type:string end
       end
    
    end
    type expirable 
    
       attribute expires type:date end
    
    end
    type fruit 
    
       inherit product; expirable end
    
       attribute country_of_origin type:string end
    
    end
  3. Type inheritance can be nested to any desired level.

    A type T4 can inherit from type T3 which inherits from T2 which inherits from T1, and so on.

    Figure 15.4. Nested type inheritance

    Nested type inheritance

    [Note]Note
    There is no limit as to the number of nesting levels allowed. However, levels above 7 appear rarely in practice and might be a sign of design that needs to be improved.

    Terminology:

    - T3 is a direct parent type of T4

    - T1 and T2 are indirect parent types of T4

    - T1, T2 and T3 are ancestor types of T4

    - T4 is a direct child type of T3

    - T4 is an indirect child type of T1 and T2

    - T4 is a descendant type of T1, T2 and T3

    - T1 is the root type of T2, T3 and T4

    Example:

    In the following example, type ebook directly inherits from book, and indirectly inherits from product:

    type product
    
       attribute identifier type:positive32 end
       attribute name type:string end
       attribute price_in_cents type:positive32 end
       
       command convert_to_XML
          out result type:string end
       end
    
    end
    type book 
    
       inherit product end
    
       attribute author type:string end
    
    end
    type ebook
    
       inherit book end
    
       attribute URL type:string end
    
    end
  4. All types implicitly inherit from type any_type.

    Type any_type is a parent type of all other types, and all types are therefore child types of type any_type.

    Type any_type is defined as follows:

    type any_type
    
        command to_string
            out result type:string end
        end command
    
        // TD object_type
        command type_proxy
            out result type:type_proxy end
        end command
    
    end type
    
  5. A type is always compatible to all its parent types.

    Whenever an object of type T is required, then any object of a type which is a child type of type T is also accepted. This makes sense, because any child type has all the features of its parent types. Therefore, a child type is always compatible to a parent type.

    Example:

    Suppose type book is a child type of type product, as follows:

    type product
    
       attribute identifier type:positive32 end
       attribute name type:string end
       attribute price_in_cents type:positive32 end
       
       command convert_to_XML
          out result type:string end
       end
    
    end
    type book 
    
       inherit product end
    
       attribute author type:string end
    
    end

    Suppose also the following service command exists to simply display a product at the system console::

    service product_service
    
       command display_product
          in product type:product end
          script
             se_console.co_message ( "product " & i_product.a_identifier.to_string & ", " & i_product.a_name )
          end
       end
    
    end

    Because book is a child type of product, book is compatible to product, which means that command display_product not only accepts objects of type product, but also objects of type book, as shown in the following code:

    var product glass = fa_product.co_create ( &
       identifier = 123 &
       name = "glass" &
       price_in_cents = 500 )
    var book book = fa_book.co_create ( &
       identifier = 124 &
       name = "Effective Java" &
       price_in_cents = 3499 &
       author = "Joshua Bloch" )
       
    product_service.display_product ( v_glass ) // allowed because glass is of type product
    product_service.display_product ( v_book )  // allowed because book is a child type of type product

    On the other hand, if type dog is defined as follows:

    type dog
       attribute name type:string end
       command bark end
    end type
    

    then an object of type dog cannot be accepted as an input for command display_product, because dog is not a child type of product (i.e. dog is not compatible to product), as shown below:

    var dog taya = fa_dog.co_create ( "Taya" )
    // product_service.display_product ( taya ) // not allowed because dog is not a child type of type product
                                                // (i.e. dog is not compatible to product)
    [Note]Note

    Because every object implicitly inherits from type any_type, the type compatibility rule implies that any object of any type can always be assigned to an object reference of type any_type (see examples below).

    Here are some more examples of valid and invalid assignments:

    var product product
    v_product = v_glass    // valid because the types are equal
    v_product = v_book     // valid because book is a child type of product
    // v_product = v_taya     // not valid because dog is not a child type of product
    
    var any_type object
    // all following assignments are valid because each type on the right side of the assignments
    // is a child type of type any_type
    v_object = v_glass
    v_object = v_book
    v_object = v_taya
    
    // all following assignments are not valid, bacause any_type is not a child type of product, book or dog
    // v_glass = v_object
    // v_book = v_object
    // v_taya = v_object
    
    // remark: ty_positive32 is a child of ty_zero_positive32, which is a child of ty_signed_integer32
    
    var signed_integer32 i32 = -10
    var zero_positive32 zp32 = 0
    var positive32 p32       = 10
    
    // valid assignments
    i32 = zp32
    i32 = p32
    zp32 = p32
    
    // invalid assignments
    // zp32 = i32
    // p32 = i32
    // p32 = zp32

    See also: the section called “case type of instruction”

  6. All identifiers of all features in all parent and child types must be unique.

    Example:

    If type T1 has attribute name, and type T2 inherits from T1, then T2 cannot have its own attribute name.

    [Note]Note

    However, T2 can redefine some properties of attribute name, as long as the type compatibility is guaranteed. See Chapter 18, Feature redefinition for more information about feature redefinition in child types.

  7. Repeated inheritance is allowed.

    Repeated inheritance occurs whenever a child type T4 inherits the same feature, f1, from two parent types T2 and T3, and f1 is defined in type T1 which is a parent of types T2 and T3.

    Figure 15.5. Repeated type inheritance

    Repeated type inheritance

    Example:

    Repeated inheritance always occurs whenever a type explicitly inherits from at least one other type, because all types inherit from type any_type.

  8. Cyclic inheritance is not allowed.

    Cyclic inheritance would occur whenever a type T2 directly or indirectly inherits from type T1, and T1 directly or indirectly inherits from T2.

    Figure 15.6. Cyclic type inheritance

    Cyclic type inheritance

    Cyclic inheritance would lead to endless recursion. If it appears in a type system it is always a sign of a design error.