Traits
[Previous]  [Next] 
|
User Manual [Previous]  [Next] TraitsA trait is a group of class content items that serves as building blocks for classes. A trait implements its main functionality through methods, state machines, and other modeling elements used for modeling behavior. Clients of traits: Clients of traits can be classes and other traits. In other words, a trait is a partial description of a class that can be reused in several different classes, and traits can form hierarchies. The client uses the isA clause to include the trait content. Enabling multiple inheritance: Traits can be used in place of standard inheritance where there is already a superclass, since multiple inheritance is not allowed in Umple to be consistent with Java and several other languages. Separation of concerns: Traits can be used to inject attributes, associations, state machines, constraints, methods and many other elements. They are one of several approaches in Umple to separation of concerns. The others are the mixin ability (ability to specify a class several times and have the elements added together), mixsets, and the aspect oriented capabilities. Note that traits themselves are subject to being mixed in. You can declare two parts of the same trait in two different places in an Umple system. Defining traits: Umple traits are defined through the keyword 'trait' followed by a unique name and a pair of curly brackets. The name must be alphanumeric and start with an alpha character, or the symbol (underscore). We also recommend capitalizing the first letter of traits names, as is the case for classes and interfaces in Umple. All elements of traits are defined inside the curly brackets except template parameters defined between the name and the curly brackets. There are separate pages describing how to incorporate attributes, state machines, template parameters, required interfaces, and associations into traits. Traits are not types: An Umple trait cannot be used as a type of a variable (whereas a class or interface can). Required methods: Traits also can have missing functionality which is defined as a set of required (abstract) methods. These required methods must be provided by clients of traits, either directly or indirectly. Required methods are defined similarly to the way abstract methods are defined in classes. They have exactly the same syntax, but it is also possible in traits to define required methods without the keyword abstract. If a method is defined like a normal method without a body (or implementation), the Umple compiler will consider that as a required method. Provided methods: These are defined in the same way as concrete methods are defined in classes. Indeed, they have exactly the same syntax and semantics. Provided methods also support multiple code blocks, for generation of systems in different languages. Diagramming: Traits are not part of UML. A UML class diagram drawn from an Umple file containing traits will 'flatten' the traits. Umple can, however, be made to generate a special diagram that shows traits; this can be requested via the Options menu in UmpleOnline and in the generate clause of the compiler. Use with mixsets: Creating a mixset that defines both a trait and isA statements incorporating the trait into clients allows the specification of optional functionality that can be mixed in to several classes. This is how mixins work in languages such as Ruby. Elements copied into client classes: The trait elements will appear in all classes that include that trait. In the first example below, the name and address attribute will appear in the class diagram of both Person and Company The example 2 below shows a trait called TEquality. It has a required methods named isEqual and a provided method named isNotEqual. The provided methods uses the required method to satisfy part of its functionality. When exploring the following examples 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: use of a trait in Umple The trait has regular attributes, derived attribute and a method that are copied into Organization and Company 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 Identifiable { firstName; lastName; address; phoneNumber; fullName = {firstName + " " + lastName} Boolean isLongName() { return lastName.length() > 1;} } class Person { isA Identifiable; } class Organization { Integer registrationNumber; } class Company { isA Organization, Identifiable; } // @@@skipcppcompile Load the above code into UmpleOnline Another Example/* Example 2: showing a trait designed for comparison regarding if two objects are equal or not. 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 TEquality{ Boolean isEqual(Object object); Boolean isNotEqual(Object object){ return isEqual(object) ? true : false; } } // @@@skipcompile Java code not compilable no class Load the above code into UmpleOnline SyntaxtraitDefinition : trait [name] [[traitParameters]]? { [[traitContent]]* } traitContent- : [[mixsetDefinition]]  | [[testCase]]  | [[requiredModelElements]]  | [[comment]]  | [[reqImplementation]]  | [[traitDefinition]]  | [[trace]]  | [[position]]  | [[displayColor]]  | [[abstract]]  | [[keyDefinition]]  | [[softwarePattern]]  | [[depend]]  | [[symmetricReflexiveAssociation]]  | [[attribute]]  | [[stateMachine]]  | [[inlineAssociation]]  | [[concreteMethodDeclaration]]  | [[abstractMethodDeclaration]]  | [[constantDeclaration]]  | [[invariant]]  | ;  | [[exception]]  | [[extraCode]] |