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:
the terminology we use is:
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
Type inheritance is governed by the following rules:
A child type can optionally define its own additional features which are not defined in its parent type(s).
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
endtype book inherit product end attribute author type:string end end
A type can inherit from several other types.
![]() | 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
endtype expirable attribute expires type:date end end
type fruit inherit product; expirable end attribute country_of_origin type:string end end
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.
![]() | 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
endtype book inherit product end attribute author type:string end end
type ebook inherit book end attribute URL type:string end end
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
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
endtype 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
endBecause 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 |
|---|---|
Because every object implicitly inherits from type |
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
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 |
|---|---|
However, |
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.
Example:
Repeated inheritance always occurs whenever a type explicitly inherits from at least one other type, because all types inherit from type any_type.
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.
Cyclic inheritance would lead to endless recursion. If it appears in a type system it is always a sign of a design error.