Thomas A. Alspaugh
Under Construction
Javadoc for examples.
What To Look For
This example works through encapsulation,
making objects do the acting,
and
extending the example's world
by adding another layer of abstraction,
twice.
The progression takes us
from requirements satisfied dynamically while the program runs,
to progressively more requirements satisfied
statically
(using the structure of the class definitions,
which mirrors the structure of the world we are working in),
and from an implementation that is fairly tricky
to one that is almost boringly straightforward
to write, and to review.
Example
Consider a mattress.
A good housewife or househusband
will extend the comfortable life of a mattress
by flipping and rotating it every few weeks
so that the strain on the mattress's internal structure
is spread around,
rather than concentrated in the same areas.
Because a mattress is a rectangular solid,
there are only three axes about which
it can sensibly be flipped;
these axes are shown in Figure 1.
The verbs
roll
,
pitch
, and
yaw
are used to describe motions of boats, airplanes,
and other objects that can rotate in three-dimensional space.
The mattress is drawn with one red end
(the head
end of the mattress),
one blue side
(the left
side of the mattress),
and one surface with a green dot
(the top
surface of the mattress).
We will term the other surfaces
the foot
,
right
side,
and bottom
surface.
Of course these names and colors are arbitrary;
it doesn't matter what we call them or how we label them,
as long as we can keep them straight.
Also because a mattress is a rectangular solid,
there are only a limited number of orientations
in which a mattress can be placed on its box springs.
These orientations are shown in Figure 2;
there are four,
named for convenience HLT, HRB, FLB, and FRT.
Note that since there are four orientations,
there are twelve (4!) ordered pairs of orientations:
- (HLT, HRB) connected by a roll
- (HLT, FRT) connected by a yaw
- (HLT, FLB) connected by a pitch
- (HRB, FRT) connected by a pitch
- (HRB, FLB) connected by a yaw
- (HRB, HLT) connected by a roll
- (FRT, FLB) connected by a roll
- (FRT, HLT) connected by a yaw
- (FRT, HRB) connected by a pitch
- (FLB, HLT) connected by a pitch
- (FLB, HRB) connected by a yaw
- (FLB, FRT) connected by a roll
You'll also note that
two pitches in a row
leave the mattress in its original orientation,
as do
two rolls or two yaws.
It's also the case
that it is possible to visit all four orientations
by doing a pitch, a roll, a pitch and a roll;
or a roll, a yaw, a roll, and a yaw;
or a yaw, a pitch, a yaw, and a pitch.
In the physical world,
three-dimensional space constrains a mattress
to only move as outlined in the figures and the list.
In our model and its implementation,
we must constrain a mattress to only move that way
with the implementation.
We can model a mattress and its flips and orientations
in object oriented fashion.
There are several sensible ways to do this,
each with its own advantages.
Here is the javadoc
for the three example ways.
Mattress1:
State implemented with several attributes,
and
the mattress does the flips
This first way to model a mattress
represents a world
consisting only of mattresses.
In the javadoc,
this world is represented by:
-
The class Mattress1,
which implements two interfaces HasHLT and PRYable.
-
Interface HasHLT
has three boolean methods
headRed(),
leftBlue(), and
topGreen()
that together state a mattress's orientation.
-
Interface PRYable
(for Pitch-, Roll-, and Yaw-able)
has three void methods
that make a mattress pitch, roll, or yaw respectively.
Thus each mattress does its own flipping.
Since we are trying to reason consistently,
the Mattress1 methods
inherit not only the signatures of each interface method
(name, parameters, return type)
but also its description.
See the javadoc
for the inherited descriptions.
This design and implementation
are conceptually straightforward.
The implementation
uses three boolean attributes
head, left, and top
to represent a mattress's state.
The values of these attributes
are visible through methods that return them,
but the values are only set
through calls to the
pitch, roll, and yaw methods.
The implementation of these methods
have to maintain the proper relationships
among the three attributes.
This design is object oriented:
it results in
objects that are not passive
(their pitch(), roll(), and yaw() methods
make the mattress do the flips),
that have state,
and that encapsulate that state.
// (c) 2010 Thomas A. Alspaugh. All rights reserved.
package oo;
/**
Something that has
a red end at the head or foot,
a blue side at the left or right,
and a green surface at the top or bottom.
*/
public interface HasHLT {
/**
A string representing the orientation,
matching [HF][LR][TB].
The string contains
H if headRed() and F otherwise;
L if leftBlue() and R otherwise; and
T if topGreen() and B otherwise.
*/
public String toString();
/**
True iff the red end is at the top.
*/
public boolean headRed();
/**
True iff the blue side is at the left.
*/
public boolean leftBlue();
/**
True iff the green surface is on the top.
*/
public boolean topGreen();
}
// (c) 2010 Thomas A. Alspaugh. All rights reserved.
package oo;
/**
Something that can pitch, roll, and yaw.
*/
public interface PRYable extends HasHLT {
/**
Rolls the thing a half-turn (180 degrees).
@return The result of the roll.
*/
public PRYable roll();
/**
Pitches the thing a half-turn (180 degrees).
@return The result of the pitch.
*/
public PRYable pitch();
/**
Yaws the thing a half-turn (180 degrees).
@return The result of the yaw.
*/
public PRYable yaw();
}
// (c) 2010 Thomas A. Alspaugh. All rights reserved.
package oo;
/**
A mattress and its orientations;
the mattress's state (its orientation)
is implemented with three booleans.
<table frame='box' rules='all'>
<tbody>
<tr>
<th> </th>
<th rowspan='7'></th>
<th colspan='3'> To, after a ... </th>
</tr>
<tr>
<th> From </th>
<th> pitch </th>
<th> roll </th>
<th> yaw </th>
</tr>
<tr>
<td colspan='5'></td>
</tr>
<tr>
<td> FLB </td>
<td> HLT </td>
<td> FRT </td>
<td> HRB </td>
</tr>
<tr>
<td> FRT </td>
<td> HRB </td>
<td> FLB </td>
<td> HLT </td>
</tr>
<tr>
<td> HLT </td>
<td> FLB </td>
<td> HRB </td>
<td> FRT </td>
</tr>
<tr>
<td> HRB </td>
<td> FRT </td>
<td> HLT </td>
<td> FLB </td>
</tr>
</tbody>
</table>
<p>
The FLB, FRT, etc. codes in the table above
are interpreted as follows:
<table frame='box' rules='all'>
<tbody>
<tr>
<th> Code </th>
<th> Meaning </th>
</tr>
<tr><th>B</th> <td> Bottom is green </td></tr>
<tr><th>F</th> <td> Foot is red </td></tr>
<tr><th>H</th> <td> Head is red </td></tr>
<tr><th>L</th> <td> Left is blue </td></tr>
<tr><th>R</th> <td> Right is blue </td></tr>
<tr><th>T</th> <td> Top is green </td></tr>
</tbody>
</table>
*/
public class Mattress1 implements PRYable {
/**
True if this mattress is oriented red-end at head.
*/
private boolean head;
/**
True if this mattress is oriented blue-end at left.
*/
private boolean left;
/**
True if this mattress is oriented green-surface at top.
*/
private boolean top;
/**
Constructs a mattress
with red-end at top,
blue-end at left,
and green-surface at top.
*/
public Mattress1() {
head = true;
left = true;
top = true;
}
public String toString() {
return
(head ? "H" : "F") +
(left ? "L" : "R") +
(top ? "T" : "B");
}
public boolean headRed() {
return head;
}
public boolean leftBlue() {
return left;
}
public boolean topGreen() {
return top;
}
public PRYable pitch() {
head = !head;
top = !top ;
return this;
}
public PRYable roll() {
left = !left;
top = !top ;
return this;
}
public PRYable yaw() {
head = !head;
left = !left;
return this;
}
}
Mattress2:
State implemented with one Orientation object,
and
the orientation does the flips
The second way to model a mattress
represents a world consisting of
mattresses and orientations.
There are exactly four orientations in this world,
no more, no less;
they have no state
and they exist all the time
(and thus are somewhat like values).
Each mattress has an orientation as its state.
Unlike for Mattress1,
in this implementation
the orientation does the flipping:
an orientation has methods for
pitch(),
roll(), and
yaw()
that return the new orientation
resulting from each of those flips.
Thus a mattress delegates flipping to its current orientation,
and the mattress takes the new orientation
that the old orientation's method returned.
The implementation still maintains the proper relationship
among the mattress's head, left, and top,
but now instead of being calculated for each flip,
the proper relationships are set at compile time.
This requirement for the mattress
has been turned from a run-time concern
into a primarily design-time concern,
with the relationships set statically
when the four orientations are constructed.
This design is even more object oriented.
It has objects that are not passive,
not only the mattresses
but also the orientations.
A mattress's state is even further encapsulated,
in another object.
Most significantly,
this design takes work that was accomplished
by Java code at run time by Mattress1,
namely keeping a mattress's state consistent
with the physical world,
and moves some of it to design time,
by embodying each of the four states
as a constant, stateless,
singleton object
of a subclass of Orientation.
Now the Java language
is ensuring that there are only four states,
and doing some of this work at compile time rather than run time.
// (c) 2010 Thomas A. Alspaugh. All rights reserved.
package oo;
/**
A mattress and its orientations;
state implemented as a single object of an inner class.
*/
public class Mattress2 implements PRYable {
/**
The mattress's orientation,
represented as a single object.
*/
private PRYable orientation;
/**
Constructs a mattress
with red-end at top,
blue-end at left,
and green-surface at top.
*/
public Mattress2() {
orientation = Orientation.HLT;
}
public String toString() {
return orientation.toString();
}
public boolean headRed() {
return orientation.headRed();
}
public boolean leftBlue() {
return orientation.leftBlue();
}
public boolean topGreen() {
return orientation.topGreen();
}
/**
The mattress's orientation.
*/
public Orientation orientation() {
return (Orientation) orientation;
}
public PRYable pitch() {
orientation = orientation.pitch();
return orientation;
}
public PRYable roll() {
orientation = orientation.roll();
return orientation;
}
public PRYable yaw() {
orientation = orientation.yaw();
return orientation;
}
}
// (c) 2010 Thomas A. Alspaugh. All rights reserved.
package oo;
/**
An orientation of a mattress.
There are four possible orientations
({@link #HLT},
{@link #HRB},
{@link #FLB}, and
{@link #FRT});
no others can be constructed.
<p>
This class ensures that the only orientations are
the four physically-possible orientations.
Each orientation is embodied by
a singleton object of a subclass of Orientation.
*/
public abstract class Orientation implements PRYable {
/**
The singleton HLT orientation.
*/
static public final Orientation HLT = OrientationHLT.singleton;
/**
The singleton HRB orientation.
*/
static public final Orientation HRB = OrientationHRB.singleton;
/**
The singleton FLB orientation.
*/
static public final Orientation FLB = OrientationFLB.singleton;
/**
The singleton FRT orientation.
*/
static public final Orientation FRT = OrientationFRT.singleton;
// ---------------------------------------------------------------
/**
"HLT", "HRB", "FLB", or "FRT",
whichever describes this orientation.
*/
private final String toString;
/**
Hidden default constructor, always throws an exception.
*/
@SuppressWarnings("unused")
private Orientation() {
throw new RuntimeException("Default constructor not to be called");
}
/**
Protected constructor for orientations.
@param _toString "HLT", "HRB", "FLB", or "FRT".
*/
protected Orientation(String _toString) {
if /**/ (_toString.equals("HLT")) { /* do nothing */ }
else if (_toString.equals("HRB")) { /* do nothing */ }
else if (_toString.equals("FLB")) { /* do nothing */ }
else if (_toString.equals("FRT")) { /* do nothing */ }
else {
throw new RuntimeException("_toString \"" + _toString + "\"");
}
toString = _toString;
}
/**
"HLT", "HRB", "FLB", or "FRT",
whichever describes this orientation.
*/
public String toString() { return toString; }
public boolean headRed() { return 'H' == toString.charAt(0); }
public boolean leftBlue() { return 'L' == toString.charAt(1); }
public boolean topGreen() { return 'T' == toString.charAt(2); }
abstract public Orientation roll();
abstract public Orientation pitch();
abstract public Orientation yaw();
/**
The HLT orientation (head, left, top).
*/
public Orientation HLT() { return OrientationHLT.singleton; }
/**
The HRB orientation (head, right, bottom).
*/
public Orientation HRB() { return OrientationHRB.singleton; }
/**
The FLB orientation (foot, left, bottom).
*/
public Orientation FLB() { return OrientationFLB.singleton; }
/**
The FRT orientation (foot, right, top).
*/
public Orientation FRT() { return OrientationFRT.singleton; }
}
/**
Singleton class for the HLT orientation.
*/
class OrientationHLT extends Orientation {
/** Singleton object of this class. */
static final OrientationHLT singleton = new OrientationHLT();
/** Private constructor for HLT. */
private OrientationHLT() {
super( "HLT");
}
public Orientation roll() { return HRB(); }
public Orientation pitch() { return FLB(); }
public Orientation yaw() { return FRT(); }
}
/**
Singleton class for the HRB orientation.
*/
class OrientationHRB extends Orientation {
/** Singleton object of this class. */
static final OrientationHRB singleton = new OrientationHRB();
/** Private constructor for HRB. */
private OrientationHRB() {
super( "HRB");
}
public Orientation roll() { return HLT(); }
public Orientation pitch() { return FRT(); }
public Orientation yaw() { return FLB(); }
}
/**
Singleton class for the FLB orientation.
*/
class OrientationFLB extends Orientation {
/** Singleton object of this class. */
static final OrientationFLB singleton = new OrientationFLB();
/** Private constructor for FLB. */
private OrientationFLB() {
super( "FLB");
}
public Orientation roll() { return FRT(); }
public Orientation pitch() { return HLT(); }
public Orientation yaw() { return HRB(); }
}
/**
Singleton class for the FRT orientation.
*/
class OrientationFRT extends Orientation {
/** Singleton object of this class. */
static final OrientationFRT singleton = new OrientationFRT();
/** Private constructor for FRT. */
private OrientationFRT() {
super( "FRT");
}
public Orientation roll() { return FLB(); }
public Orientation pitch() { return HRB(); }
public Orientation yaw() { return HLT(); }
}
Mattress3:
The flips are objects too;
now they flip each other
The second way to model a mattress
promoted the formerly abstract orientations,
which had been embodied in groups of attributes,
to be individual objects instead.
The third way to model a mattress
continues this trend
by additionally promoting
the three abstract flips
(pitch, roll, yaw),
which were embodied
in the method implementations of
Mattress1 and then Orientation,
into individual objects.
A flip takes an orientation
and returns the next orientation:
it is a unary operation on orientations.
Now that flips are objects,
we can also consider operations on flips.
The appropriate mathematical operation
is composition
of two flips.
We express this with a method
Flip composeWith(Flip _other)
that takes a flip _other
and returns a composition of the flip with _other.
If we call x.flip(y),
the result is x.y or
the flip that produces the same result
as x followed by y.
Now instead of performing a sequence of flips of mattress objects,
we can figure out what would happen if we did
by composing flip objects.
The implementation of Flip
uses the run-time type of flips
to select the right composition result using Java's type system:
-
Each subclass S's composeWith(Flip _other) method
is implemented identically:
public Flip composeWith(Flip _other) {
return _other.composedWith(this);
}
It calls _other's composedWith(S) method,
using the type of this (S) to select among
_other's four composedWith() methods.
-
Each subclass's four composedWith() methods
have very simple implementations,
each one simply returning the appropriate flip.
For example,
FlipPITCH's composeWith(FlipROLL) method is
Flip composedWith(FlipROLL _other) { return YAW; }
No run-time calculation is needed because
a pitch followed by a roll is always the same as a yaw.
As a result,
the implementations of the Flip subclasses
are very simple,
easy to write (once the fairly sophisticated design is done)
and
easy to check for correctness.
Notice how as we progressed
from the initial design,
beginning with orientations expresssed
as a group of attributes,
then expressing the abstract orientations as objects,
and finally
expressing the abstract flips as objects,
more and more of the code
has become very very simple.
Might one even say there are
obviously no deficiencies
?
We have moved work from run time,
where it is more difficult to review
and for which testing is needed,
to design time (and compile time),
where it can be simpler to review,
and some of the verification can be done
by the compiler (because some of the work is done by the type system).
// (c) 2010 Thomas A. Alspaugh. All rights reserved.
package oo;
/**
A mattress and its orientations;
state implemented as a single object of an inner class.
*/
public class Mattress3 implements PRYable {
/**
True if this mattress is oriented red-end at head.
*/
private Orientation orientation;
/**
Constructs a mattress
with red-end at top,
blue-end at left,
and green-surface at top.
*/
public Mattress3() {
orientation = Orientation.HLT;
}
public String toString() {
return orientation.toString();
}
public boolean headRed() {
return orientation.headRed();
}
public boolean leftBlue() {
return orientation.leftBlue();
}
public boolean topGreen() {
return orientation.topGreen();
}
/**
The mattress's orientation.
*/
public Orientation orientation() {
return orientation;
}
public PRYable pitch() {
orientation = Flip.PITCH.flip(orientation);
return this;
}
public PRYable roll() {
orientation = Flip.ROLL.flip(orientation);
return this;
}
public PRYable yaw() {
orientation = Flip.YAW.flip(orientation);
return this;
}
}
// (c) 2010 Thomas A. Alspaugh. All rights reserved.
package oo;
/**
A flip (a pitch, roll, yaw, or null flip having no effect)
used by <tt>Mattress3</tt>'s implementation.
<p>
Each of its four subclasses implements its
{@link #composeWith(Flip)} method identically,
by returning <tt>_other.composedWith(this)</tt>.
This selects (at compile time)
the appropriate <tt>composedWith</tt> method
for <tt>composedWith</tt>'s run-time argument:
<ol>
<li> {@link #composedWith(FlipNULL)} </li>
<li> {@link #composedWith(FlipPITCH)} </li>
<li> {@link #composedWith(FlipROLL)} </li>
<li> {@link #composedWith(FlipYAW)} </li>
</ol>
<p>
Each subclass's four <tt>composedWith</tt> methods
then simply returns the single possible result
for the parameter type.
<p>
The result of composing non-{@link #NULL} flips A and B
follows a simple pattern
that can be verified
by examining <q>OO Examples</q>
<a href='../../oo-example.html#Figure2'>Figure 2</a>:
</p>
<table frame='box' rules='all'>
<tbody>
<tr>
<th> The two cases </th>
<th> A composed with B </th>
</tr>
<tr>
<td> A == B </td>
<td> {@link #NULL} </td>
</tr>
<tr>
<td> A != B </td>
<td> The other non-{@link #NULL} flip </td>
</tr>
</tbody>
</table>
<p>
The figure also shows that composition of flips is
<a href='../../operation.html#commutative'>commutative</a>.
<p>
Of course,
the {@link #NULL} flip when composed with any other flip C
is that same flip C
(including the case where C is itself {@link #NULL}).
</p>
*/
abstract public class Flip {
/**
A <q>null flip</q> that does nothing to an orientation.
*/
static public final FlipNULL NULL = new FlipNULL();
/**
A pitch through a half turn (180°)
*/
static public final FlipPITCH PITCH = new FlipPITCH();
/**
A roll through a half turn (180°)
*/
static public final FlipROLL ROLL = new FlipROLL();
/**
A yaw through a half turn (180°)
*/
static public final FlipYAW YAW = new FlipYAW();
/**
Protected default constructor,
can only be called by subclasses of Flip.
*/
protected Flip() { }
/**
The flip's name
(<q>null</q>, <q>pitch</q>, <q>roll</q>, or <q>yaw</q>).
*/
abstract public String toString();
/**
Package-private method composing this flip with a null flip.
@throws NullPointerException If _other is <tt>null</tt>.
@return This flip.
*/
abstract Flip composedWith(FlipNULL _other);
/**
Package-private method composing this flip with a FlipPITCH.
@throws NullPointerException If _other is <tt>null</tt>.
*/
abstract Flip composedWith(FlipPITCH _other);
/**
Package-private method composing this flip with a FlipROLL.
@throws NullPointerException If _other is <tt>null</tt>.
*/
abstract Flip composedWith(FlipROLL _other);
/**
Package-private method composing this flip with a FlipYAW.
@throws NullPointerException If _other is <tt>null</tt>.
*/
abstract Flip composedWith(FlipYAW _other);
/**
Composes this flip with _other,
resulting in a flip.
@throws NullPointerException If _other is <tt>null</tt>.
*/
abstract public Flip composeWith(Flip _other);
/**
Applies this flip to an orientation,
producing an orientation.
@throws NullPointerException If _initial is <tt>null</tt>.
*/
abstract public Orientation flip(Orientation _initial);
}
/**
Package-private singleton class
for the null flip that has no effect when applied to an orientation.
*/
class FlipNULL extends Flip {
/** Package private constructor for null flip. */
FlipNULL() {}
public String toString() { return "null"; }
/**
@return {@link #NULL}.
*/
Flip composedWith(FlipNULL _other) {
if (null == _other) { throw new NullPointerException("_other"); }
return _other;
}
/**
@return <tt>_other</tt>.
*/
Flip composedWith(FlipPITCH _other) {
if (null == _other) { throw new NullPointerException("_other"); }
return _other;
}
/**
@return <tt>_other</tt>.
*/
Flip composedWith(FlipROLL _other) {
if (null == _other) { throw new NullPointerException("_other"); }
return _other;
}
/**
@return <tt>_other</tt>.
*/
Flip composedWith(FlipYAW _other) {
if (null == _other) { throw new NullPointerException("_other"); }
return _other;
}
public Flip composeWith(Flip _other) {
if (null == _other) { throw new NullPointerException("_other"); }
return _other.composedWith(this);
}
public Orientation flip(Orientation _initial) {
if (null == _initial) { throw new NullPointerException("_initial"); }
return _initial;
}
}
/**
Package-private singleton class
for a pitch.
*/
class FlipPITCH extends Flip {
/** Package private constructor for pitch. */
FlipPITCH() {}
public String toString() { return "pitch"; }
Flip composedWith(FlipNULL _other) {
if (null == _other) { throw new NullPointerException("_other"); }
return PITCH;
}
/**
@return {@link #NULL}.
*/
Flip composedWith(FlipPITCH _other) {
if (null == _other) { throw new NullPointerException("_other"); }
return NULL;
}
/**
@return {@link #YAW}.
*/
Flip composedWith(FlipROLL _other) {
if (null == _other) { throw new NullPointerException("_other"); }
return YAW;
}
/**
@return {@link #ROLL}.
*/
Flip composedWith(FlipYAW _other) {
if (null == _other) { throw new NullPointerException("_other"); }
return ROLL;
}
public Flip composeWith(Flip _other) {
if (null == _other) { throw new NullPointerException("_other"); }
return _other.composedWith(this);
}
public Orientation flip(Orientation _initial) {
if (null == _initial) { throw new NullPointerException("_initial"); }
return (Orientation) _initial.pitch();
}
}
/**
Package-private singleton class for a roll.
*/
class FlipROLL extends Flip {
/** Package private constructor for roll. */
FlipROLL() {}
public String toString() { return "roll"; }
Flip composedWith(FlipNULL _other) {
if (null == _other) { throw new NullPointerException("_other"); }
return ROLL;
}
/**
@return {@link #YAW}.
*/
Flip composedWith(FlipPITCH _other) {
if (null == _other) { throw new NullPointerException("_other"); }
return YAW;
}
/**
@return {@link #NULL}.
*/
Flip composedWith(FlipROLL _other) {
if (null == _other) { throw new NullPointerException("_other"); }
return NULL;
}
/**
@return {@link #PITCH}.
*/
Flip composedWith(FlipYAW _other) {
if (null == _other) { throw new NullPointerException("_other"); }
return PITCH;
}
public Flip composeWith(Flip _other) {
if (null == _other) { throw new NullPointerException("_other"); }
return _other.composedWith(this);
}
public Orientation flip(Orientation _initial) {
if (null == _initial) { throw new NullPointerException("_initial"); }
return (Orientation) _initial.roll();
}
}
/**
Package-private singleton class for a yaw.
*/
class FlipYAW extends Flip {
/** Package private constructor for yaw. */
FlipYAW() {}
public String toString() { return "yaw"; }
Flip composedWith(FlipNULL _other) {
if (null == _other) { throw new NullPointerException("_other"); }
return YAW;
}
/**
@return {@link #ROLL}.
*/
Flip composedWith(FlipPITCH _other) {
if (null == _other) { throw new NullPointerException("_other"); }
return ROLL;
}
/**
@return {@link #PITCH}.
*/
Flip composedWith(FlipROLL _other) {
if (null == _other) { throw new NullPointerException("_other"); }
return PITCH;
}
/**
@return {@link #NULL}.
*/
Flip composedWith(FlipYAW _other) {
if (null == _other) { throw new NullPointerException("_other"); }
return NULL;
}
public Flip composeWith(Flip _other) {
if (null == _other) { throw new NullPointerException("_other"); }
return _other.composedWith(this);
}
public Orientation flip(Orientation _initial) {
if (null == _initial) { throw new NullPointerException("_initial"); }
return (Orientation) _initial.yaw();
}
}