list of dots Digital Research Alliance of Canada logo  NSERC logo  University of Ottawa logo / UniversitĂ© d'Ottawa

User Manual    [Previous]   [Next]   

Clients of Traits

Traits are used by clients (classes and traits) by specifying the keyword 'isA' followed by their names and a semi-colon. Traits cannot use themselves (even through several uses in a cyclic manner). When clients specify names of traits for use, those traits must exist in the system. If a trait uses more than one trait, it can separate them by comma or use the keyword 'isA' for each one.

In the example 1 below, trait T2 is a client that uses trait T1 (at line 11) and class C2 is a client that uses trait T2 (at line 21). Clients can use other traits if they satisfy their required methods. Satisfaction of required methods is performed by having them implemented in clients. For example, trait T2 uses trait T1 and so it is required to have the required methods of trait T1 implemented in trait T2 (or in clients of trait T2). Trait T2 achieves this through implementing two methods named method1() and method2() defined in lines 13 and 14.

Trait T2 is not a final client, therefore, it could use trait T1 without implementing those required methods, in that case, the required methods of trait T2 would be method1(), method2(), and method 3(). Class C2, which is a final client, uses trait T2 and therefore needs to implement the remaining required method method3(). However, there is no direct implementation for it. Instead, class C2 obtains such an implementation indirectly from its superclass, which is C1. Therefore, it satisfies the required method of trait T2.

When clients use traits, they obtain all provided methods defined in the traits. This includes all other provided methods those traits might obtain from their own used traits. For example, trait T2 gets the provided method method4() from trait T1. This provided method can be called by all other provided methods defined in trait T2. Therefore trait T2 provides three provided methods named method1(), method2(), and method4(). Class C2 uses trait T2 and so it obtains all provided methods.

Note that it is allowed for abstract classes to use traits without satisfying their required methods. Such required methods are then considered as abstract methods of the abstract class. Then, all concrete subclasses of the abstract class are required to implement those abstract methods. This process ensures that required methods will finally be implemented. It is worth noting that interfaces cannot use traits because they cannot have concrete methods in their definitions.

When exploring the following example in UmpleOnline, you can use the Options menu to control what is visible, or you can use control-R to flip back and forth between showing the diagram with the original traits, vs. the diagram collapsed into the classes to be compiled; or you can use control-M to show/hide methods.

Example

/*
  Example 1: showing how traits can be used by
  their clients.
  
  To see different diagram views in UmpleOnline:
    Use control-g for auto-layout
      (if not already showing)
    Use control-r to switch between trait view and
       plain classes resulting from applying traits
    Use control-m to show/hide methods
*/
trait T1{
  abstract void method1();
  abstract void method2();
  void method4() Java {/*implementation*/ }
  void method4() Python { ''' implementation ''' }
}
trait T2{
  isA T1;
  void method3();
  void method1() Java {/*implementation*/ }
  void method2() Java {/*implementation*/ }
  void method1() Python { ''' implementation ''' }
  void method2() Python { ''' implementation ''' }
}
class C1{
  void method3() Java {/*implementation*/ }
  void method3() Python { ''' implementation ''' }
}
class C2{
  isA C1;
  isA T2;
  void method2() Java {/*implementation*/ }
  void method2() Python { ''' implementation ''' }
}
      

Load the above code into UmpleOnline