FHJ: A Formal Model for Hierarchical Dispatching and Overriding

Multiple inheritance is a valuable feature for Object-Oriented Programming. However, it is also tricky to get right, as illustrated by the extensive literature on the topic. A key issue is the ambiguity arising from inheriting multiple parents, which can have conﬂicting methods. Numerous existing work provides solutions for conﬂicts which arise from diamond inheritance : i.e. conﬂicts that arise from implementations sharing a common ancestor. However, most mechanisms are inadequate to deal with unintentional method conﬂicts : conﬂicts which arise from two unrelated methods that happen to share the same name and signature. This paper presents a new model called F eatherweight H ierarchical J ava ( FHJ ) that deals with unintentional method conﬂicts. In our new model, which is partly inspired by C++, con-ﬂicting methods arising from unrelated methods can coexist in the same class, and hierarchical dispatching supports unambiguous lookups in the presence of such conﬂicting methods. To avoid ambiguity, hierarchical information is employed in method dispatching, which uses a combination of static and dynamic type information to choose the implementation of a method at run-time. Furthermore, unlike all existing inheritance models, our model supports hierarchical method overriding : that is, methods can be independently overridden along the multiple inheritance hierarchy. We give illustrative examples of our language and features and formalize FHJ as a minimal Featherweight-Java style calculus.


Introduction
Inheritance in Object-Oriented Programming (OOP) offers a mechanism for code reuse.However many OOP languages are restricted to single inheritance, which is less expressive and flexible than multiple inheritance.Nevertheless, different flavours of multiple inheritance have been adopted in some popular OOP languages.C++ has had multiple inheritance from the start.Scala adapts the ideas from traits [28,9,16] and mixins [5,11,32,2,13] to offer a disciplined form of multiple inheritance.Java 8 offers a simple variant of traits, disguised as interfaces with default methods [12].A reason why programming languages have resisted to multiple inheritance in the past is that, as Cook [7] puts it, "multiple inheritance is good but there is no good way to do it".One of the most sensitive and critical issues is perhaps the ambiguity introduced by multiple inheritance.One case is the famous diamond problem [27,29] (also known as the fork-join inheritance [27]).In the diamond problem, inheritance allows one feature to be inherited from multiple parent classes that share a common ancestor.Hence conflicts arise.The variety of strategies for resolving such conflicts urges the occurrence of different multiple inheritance models, including traits, mixins, CZ [17], and many others.Existing languages and research have addressed the issue of diamond inheritance extensively.Other issues including how multiple inheritance deals with state, have also been discussed quite extensively [33,17,31].
In contrast to diamond inheritance, the second case of ambiguity is unintentional method conflicts [28].In this case, conflicting methods do not actually refer to the same feature.In a nominal system, methods can be designed for different functionality but happen to have the same names (and signatures).A simple example of this situation is two draw methods that are inherited from a deck of cards and a drawable widget, respectively.In such context, the two draw methods have very different meanings, but they happen to share the same name.When inheritance is used to compose these classes, a compilation error happens due to conflicts.However, unlike the diamond problem, the conflicting methods have very different meanings and do not share a common parent.We call such a case fork inheritance, in analogy to diamond inheritance.
When unintentional method conflicts happen, they can have severe effects in practice if no appropriate mechanisms to deal with them are available.In practice, existing languages only provide limited support for the issue.In most languages, the mechanisms available to deal with this problem are the same as the diamond inheritance.However, this is often inadequate and can lead to tricky problems in practice.This is especially the case when it is necessary to combine two large modules and their features, but the inheritance is simply prohibited by a small conflict.As a workaround from the diamond inheritance side, it is possible to define a new method in the child class to override those conflicting methods.However, using one method to fuse two unrelated features is clearly unsatisfactory.Therefore we need a better solution to keep both features separately during inheritance, so as not to break independent extensibility [36].
C++ and C# do allow for two unintentionally conflicting methods to coexist in a class.C# allows this by interface multiple inheritance and explicit method implementations.But since C# is a single inheritance language, it is only possible to implement multiple interfaces (but not multiple classes).C++ accepts fork inheritance and resolves the ambiguity by specifying the expected path by upcasts.However, neither the C# nor C++ approaches allow such conflicting methods to be further overridden.Some other workarounds or approaches include delegation and renaming/exclusion in the trait model.However, renaming/exclusion can break the subtyping relation between a subclass and its parent.This is not adequate for the class model commonly used in mainstream OOP languages, where the subclass is always expected to be a subtype of the parent class.This paper proposes two mechanisms to deal with unintentional method conflicts: hierarchical dispatching and hierarchical overriding.Hierarchical dispatching is inspired by the mechanisms in C++ and provides an approach to method dispatching, which combines static and dynamic information.Using hierarchical dispatching, the method binder will look at both the static type and the dynamic type of the receiver during runtime.When there are multiple branches that cause unintentional conflicts, the static type can specify one branch among them for unambiguity, and the dynamic type helps to find the most specific implementation.In that case, both unambiguity and extensibility are preserved.The main novelty over existing work is the formalization of the essence of a hierarchical dispatching algorithm, which (as far as we know) has not been formalized before.
Hierarchical overriding is a novel language mechanism that allows method overriding to be applied only to one branch of the class hierarchy.Hierarchical overriding adds expressive power that is not available in languages such as C++ or C#.In particular, it allows overriding to work for classes with multiple (conflicting) methods sharing the same names and signatures.An example is presented in Figure 1.In this example, there are 4 classes/interfaces.Two classes Deck and Drawable model a deck of cards and a drawable widget, respectively.The class SafeDeck adds functionality to check whether the deck is empty so as to prevent drawing a card from an empty deck.The interesting class is DrawableSafeDeck, which inherits from both SafeDeck and Drawable.Hierarchical overriding is used in DrawableSafeDeck to keep two separate draw methods for each parent, but override only the draw method coming from Drawable, in order to draw a widget with a deck of cards.Note that hierarchical overriding is denoted in the UML diagram with the notation draw()↑Drawable, expressing that the draw method from Drawable is overridden.Although in this example only one of the draw methods is overridden (and the other is simply inherited), hierarchical overriding supports multiple conflicting methods to be independently overridden as well.
To present hierarchical overriding and dispatching, we introduce a formalized model FHJ in Section 3 based on Featherweight Java [14], together with theorems and proofs for type soundness.We also have a prototype implementation of an FHJ interpreter written in Scala.The implementation validates all the examples presented in the paper.One nice feature of the implementation is that it can show the detailed step-by-step evaluation of the program, which is convenient for understanding and debugging programs & semantics.
In summary, our contributions are: A formalization of the hierarchical dispatching algorithm that integrates both the static type and dynamic type for method dispatch, and ensures unambiguity as well as extensibility in the presence of unintentional method conflicts.
Hierarchical overriding: a novel notion that allows methods to override individual branches of the class hierarchy.

A Running Example: Drawable Deck
This section illustrates the problem of unintentional method conflicts, together with the features of our model for addressing this issue, by a simple running example.In the following text, we will introduce three problems one by one and have a discussion on possible workarounds and our solutions.Problems 1 and 2 are related to hierarchical dispatching, and in C++ it is possible to have similar solutions to both problems.Hence it is important to emphasize that, with respect to hierarchical dispatching, our model is not a novel mechanism.Instead, inspired by the C++ solutions, our contribution is formalizing a minimal calculus of this feature together with a proof of type soundness.However, for the final problem, there is no satisfactory approach in existing languages, thus what we propose is a novel feature (hierarchical overriding) with the corresponding formalization of that feature.
In the rest of the paper, we use a Java-like syntax for programs.All types are defined with the keyword interface ; the concept is closely related to Java 8 interfaces with default methods [4] and traits.In short, an interface in our model has the following characteristics: It allows multiple inheritance.Every method is either abstract or implemented with a body (like Java 8 default methods).
The new keyword is used to instantiate an interface.It cannot have state.

Problem 1: Basic Unintentional Method Conflicts
Suppose that two components Deck and Drawable have been developed in a system.Deck represents a deck of cards and defines a method draw for drawing a card from the deck.
Drawable is an interface for graphics that can be drawn and also includes a method called draw for visual display.For simple illustration, the default implementation of the draw in Drawable only creates a blank canvas on the screen, while the draw method in Deck simply prints out a message In Deck, draw uses println, which is a library function.The two draw methods can have different return types, but for simplicity, the return types are both void here.Note that, similarly to Featherweight Java [14], void is unsupported in our formalization.We could have also defined an interface called Void and return an object of that type instead.To be concise, however, we use void in our examples.In interface Drawable, the draw method creates a blank canvas.Now, suppose that a programmer is designing a card game with a GUI.He may want to draw a deck on the screen, so he first defines a drawable deck using multiple inheritance: interface DrawableDeck extends Drawable, Deck {} The point of using multiple inheritance is to compose the features from various components and to achieve code reuse, as supported by many mainstream OO languages.Nevertheless, at this point, languages like Java simply treat the two draw methods as the same, hence the compiler fails to compile the program and reports an error.This case is an example of a so-called unintentional method conflict.It arises when two inherited methods happen to have the same name and parameter types, but they are designed for different functionalities with different semantics.Now one may quickly come up with a workaround, which is to manually merge the two methods by creating a new draw method in DrawableDeck to override the old ones.However, merging two methods with totally different functionalities does not make any sense.This non-solution would hide the old methods and break independent extensibility.

Problem and Possible Workarounds
The essential problem is how to resolve unintentional method conflicts and invoke the conflicting methods separately without ambiguity.To tackle this problem, there are several other workarounds that come to our mind.We briefly discuss those potential fixes and workarounds next: I. Delegation.As an alternative to multiple inheritance, delegation can be used by introducing two fields (or field methods) with the Drawable type and Deck type, respectively.Although it avoids method conflicts, it is known that using delegation makes it hard to correctly maintain self-references in an extensible system and also introduces a lot of boilerplate code.II.Refactor Drawable and/or Deck to rename the methods.If the source code for Drawable or Deck is available then it may be possible to rename one of the draw methods.However, this approach is non-modular, as it requires modifying existing code and becomes impossible if the code is unavailable.III.Method exclusion/renaming.Eiffel [18] and some trait models support method exclusion/renaming.Those features can eliminate conflicts, although most programming languages do not support them.In a traditional OO system, they can break the subtyping relationship.Moreover, in contrast with exclusion, renaming can indeed preserve both conflicting behaviours.However, it is cumbersome in practice, as introducing new names can affect other code blocks.

FHJ's solution
To solve this problem it is important to preserve both conflicting methods during inheritance instead of merging them into a single method.Therefore FHJ accepts the definition of DrawableDeck.To disambiguate method calls, we can use upcasts in FHJ to specify the "branch" in the inheritance hierarchy that should be called.The following code illustrates the use of upcasts for disambiguation: In our language, a program consists of interfaces declarations and a main an expression which produces the final result.In the above main expression ((Deck) new DrawableDeck()).draw(),the cast indicates that we expect to invoke the draw method from the branch Deck.Similarly, we could have used an upcast to Drawable to call the draw method from Drawable.Without the cast, the call would be ambiguous and FHJ's type system would reject it.This example illustrates the basic form of fork inheritance, where two unintentionally conflicting methods are accepted by multiple inheritance.Note that C++ supports this feature and also addresses the ambiguity by upcasts.The code for the above example in C++ is similar.

Problem 2: Dynamic Dispatching
Using explicit upcasts for disambiguation helps when making calls to classes with conflicting methods, but things become more complicated with dynamic dispatching.Dynamic dispatching is very common in OO programming for code reuse.Let us expand the previous example a bit, by redefining those interfaces with more features: Without dynamic dispatching, we may have to copy the shuffleAndDraw code into SafeDeck , so that shuffleAndDraw calls the new draw defined in SafeDeck.Dynamic dispatching immediately saves us from the duplication work, since the method becomes automatically dispatched to the most specific one.Nevertheless, as seen before, dynamic dispatch would potentially introduce ambiguity.For instance, when we have the class hierarchy structure shown in Figure 2 When the DrawableSafeDeck object calls shuffleAndDraw, the implementation in Deck is dispatched.But then shuffleAndDraw invokes " this .draw()",and at this point, the receiver is replaced by the object new DrawableSafeDeck().From the perspective of DrawableSafeDeck, the draw method seems to be ambiguous since DrawableSafeDeck inherits two draw methods from both SafeDeck and Drawable.But ideally we would like shuffleAndDraw to invoke SafeDeck.drawbecause they belong to the same class hierarchy branch.

FHJ's solution
The essential problem is how to ensure that the correct method is invoked.To solve this problem, FHJ uses a variant of method dispatching that we call hierarchical dispatching.In hierarchical dispatching, both the static and dynamic type information are used to select the right method implementation.During runtime, a method call makes use of both the static type and the dynamic type of the receiver, so it is a combination of static and dynamic dispatching.Intuitively, the static type specifies one branch to avoid ambiguity, and the dynamic type finds the most specific implementation on that branch.To be specific, the following code is accepted by FHJ:

20:8 FHJ: A Formal Model for Hierarchical Dispatching and Overriding
Notably, we track the static types by adding upcasts during reduction.In contrast to FJ, where new C() is a value, in FHJ such an expression is not a value.Instead, an expression of the form new C() is reduced to (C) new C(), which is a value in FHJ and the cast denotes the static type of the expression.This rule is applied in the first reduction step.In the second reduction step, when shuffleAndDraw is dispatched, the receiver (DrawableSafeDeck)new DrawableSafeDeck() replaces the special variable this by (Deck) new DrawableSafeDeck().Here, the static type used in the cast (Deck) denotes the origin of the shuffleAndDraw method, which is discovered during method lookup.Later, in the fourth step, ((Deck) new DrawableSafeDeck()).draw() is an instance of hierarchical invocation, which can be read as "finding the most specific draw above DrawableSafeDeck and along path Deck".
The meaning of "above DrawableSafeDeck" implies its supertypes, and "along path Deck" specifies the branch.Finally, in the last reduction step, we find the most specific version of draw in SafeDeck.In this sequence of reduction steps, the cast that tracks the origin of shuffleAndDraw is crucial to unambiguously find the correct implementation of draw.The formal procedure will be introduced in Section 3 and Section 4.

Problem 3: Overriding on Individual Branches
Method overriding is common in Object-Oriented Programming.With diamond inheritance, where conflicting methods are intended to have the same semantics, method overriding is not a problem.If conflicting methods arise from multiple parents, we can override all those methods in a single unified (or merged) method in the subclass.Therefore further overriding is simple, because there is only one method that can be overridden.With unintentional method conflicts, however, the situation is more complicated because different, separate, conflicting methods can coexist in one class.Ideally, we would like to support overriding for those methods too, in exactly the same way that overriding is available for other (non-conflicting) methods.However, we need to be able to override the individual conflicting methods, rather than overriding all conflicting methods into a single merged one.
We illustrate the problem and the need for a more refined overriding mechanism with an example.Suppose that the programmer defines a new interface DrawableSafeDeck (based on the code in Section 2.2 without the old DrawableSafeDeck), but he needs to override Drawable.drawand give a new implementation of drawing so that the deck can indeed be visualized on the canvas.

Potential solutions/workarounds in existing languages
Unfortunately in all languages we know of (including C++), the existing approaches are unsatisfactory.One direction is to simply avoid this issue, by putting overriding before inheritance.For example, as shown in Figure 2 This workaround seems to work, but there are severe issues: It changes the hierarchy and existing code, hence breaks the modularity.
Separate overriding is required to come after the fork inheritance, especially when the implementation needs functionality from both parents.In the above code, we have assumed that the overriding is unrelated to Deck.But when the drawing relies on some information of the Deck object, we have to either introduce field methods for delegation or change the signature of draw to take a parameter.Either way introduces unnecessary complexity and affects extensibility.
There are more involved workarounds in C++ using templates and complex patterns, but such patterns are complex to use and there are still issues.A more detailed discussion of such an approach is presented in Section 6.2.

FHJ's solution
An additional feature of our model is hierarchical overriding.It allows conflicting methods to be overridden on individual branches, hence offers independent extensibility.The above example can be easily realized by: The UML graph is shown in Figure 2(right), where the up-arrow ↑ is short for "override".Here the idea is that only Drawable.draw is overridden.This is accomplished by specifying, in the method definition, that the method only overrides the draw from Drawable.The individual overriding allows us to make use of the methods from SafeDeck as well.In the formalization, the hierarchical overriding feature is an important feature, involved in the algorithm of hierarchical dispatch.
Note that, although the example here only shows one conflicting method being overridden, hierarchical overriding allows (as expected) multiple conflicting methods to be overridden in the same class.

Terminology
In Drawable, Deck, and SafeDeck, the draw methods are called original methods in this paper, because they are originally defined by the interfaces.In contrast, DrawableSafeDeck defines a hierarchical overriding method.The difference is that traditional method overriding overrides all branches by defining another original method, whereas hierarchical overriding only refines one branch.
A special rule for hierarchical overriding is: it can only refine original methods, and cannot jump over original methods with the same signature.For instance, writing "void draw() override Deck {...}" is disallowed in DrawableSafeDeck, because the existing two branches are Drawable.drawand SafeDeck.draw,while Deck.draw is already covered.It does not really make sense to refine the old branch Deck.

A peek at the hierarchical dispatching algorithm
In FHJ, fork inheritance allows several original methods (branches) to coexist, and hierarchical dispatch first finds the most specific original method (branch), then it finds the most specific hierarchical overriding on that branch.Before the formalized algorithm, Figure 3 gives a peek at the behavior using a few examples.The UML diagrams present the hierarchy.In (d) and (e), a cross mark indicates that the interface fails to type-check.Generally, FHJ rejects the definition of an interface during compilation if it reaches a diamond with ambiguity.mbody is the method lookup function for hierarchical dispatch, formally defined in Section 4.1.In general, mbody(m, X, Y) = (Z, ...) reflects that the source code ((Y) new X()).m()calls Z.m at runtime.It is undefined when method dispatch is ambiguous.
In Figure 3, (a) is the base case for unintentional conflicts, namely the fork inheritance.(b) uses overriding to explicitly merge the conflicting methods.(c) represents hierarchical overriding.
Furthermore, our model supports diamond inheritance and can deal with diamond problems.For example, (d) and (e) are two base cases of diamond inheritance in FHJ and the definition of each C is rejected because T is an ambiguous parent to C. One solution for diamond inheritance is to merge methods coming from different parents.(f) gives a common solution to the diamond as in Java or traits, which is to explicitly override A.m and B.m in C.And our calculus supports this kind of merging methods.In the last three examples, conflicting methods A.m and B.m should be viewed as intentional conflicts, as they come from the same source T .

Formalization
In this section, we present a formal model called FHJ (Featherweight Hierarchical Java), following a similar style as Featherweight Java [14].FHJ is a minimal core calculus that formalizes the core concept of hierarchical dispatching and overriding.The syntax, typing rules and small-step semantics are presented.

Syntax
The abstract syntax of FHJ interface declarations, method declarations, and expressions is given in Figure 4.The multiple inheritance feature of FHJ is inspired by Java 8 interfaces, which supports method implementations via default methods.This feature is closely related to traits.To demonstrate how unintentional method conflicts are untangled in FHJ, we only focus on a small subset of the interface model.For example, all methods declared in an interface are either default methods or abstract methods.Default methods provide default implementations for methods.Abstract methods do not have a method body.Abstract methods can be overridden with future implementations.

Notations
The metavariables I, J, K range over interface names; x ranges over variables; m ranges over method names; e ranges over expressions; and M ranges over method declarations.Following Featherweight Java, we assume that the set of variables includes the special variable this, which cannot be used as the name of an argument to a method.We use the same conventions as FJ; we write I as shorthand for a possibly empty sequence I 1 , ..., I n , which may be indexed by I i ; and write M as shorthand for M 1 ...M n (with no commas).We also abbreviate operations on pairs of sequences in an obvious way, writing I x for I 1 x 1 , ..., I n x n , where n is the length of I and x.

Interfaces
In order to achieve multiple inheritance, an interface can have a set of parent interfaces, where such a set can be empty.Moreover, as usual in class-based languages, the extension relation over interfaces is acyclic.The interface declaration interface I extends I {M} introduces an interface named I with parent interfaces I and a suite of methods M. The methods of I may either override methods that are already defined in I or add new functionality special to I, we will illustrate this in more detail later.

Methods
Original methods and hierarchically overriding methods share the same syntax in our model for simplicity.The concrete method declaration I m(I x x) override J {return e; } introduces a method named m with result type I, parameters x of type I x and the overriding target J.The body of the method simply includes the returned expression e. Notably, we have introduced the override keyword for two cases.Firstly, if the overridden interface is exactly the enclosing interface itself, then such a method is seen as originally defined.Note that the case of merging methods from different branches, also counts as originally defined.Secondly, for all other cases the method is considered a hierarchical overriding method.Note that in an interface J, I m(I x x) {return e; } is syntactic sugar for I m(I x x) override J {return e; }, which is the standard way to define methods in Java-like languages.The definition of abstract methods is written as I m(I x x) override J ;, which is similar to a concrete method but without the method body.For simplicity, overloading is not modelled for methods, which implies that we can uniquely identify a method by its name.

Expressions & Values
Expressions can be standard constructs such as variables, method invocation, object creation, together with cast expressions.Object creation is represented by new I() 3 .Fields and primitive types are not modelled in FHJ.The casts are merely safe upcasts, and in fact, they can be viewed as annotated expressions, where the annotation indicates its static type.The coexistence of static and dynamic types is the key to hierarchical dispatch.A value "(I)new J()" is the final result of multiple reduction steps for evaluating an expression.For simplicity, FHJ does not formalize statements like assignments and so on because they are orthogonal features to the hierarchical dispatching and overriding feature.A program in FHJ consists of a list of interface declarations, plus a single expression.

Subtyping
The subtyping of FHJ consists of only a few rules shown at the top of Figure 5.In short, subtyping relations are built from the inheritance in interface declarations.Subtyping is both reflexive and transitive.

Type-checking
Details of type-checking rules are displayed at the bottom of Figure 5, including expression typing, well-formedness of methods and interfaces.As a convention, an environment Γ is maintained to store the types of variables, together with the self-reference this.
(T-Invk) is the typing rule for method invocation.Naturally, the receiver and the arguments are required to be well-typed.mbody is our key function for method lookup that implements the hierarchical dispatching algorithm.The formal definition will be introduced in Section 4.Here mbody(m, I 0 , I 0 ) finds the most specific m above I 0 ."Above I 0 " specifies the search space, namely the supertypes of I 0 including itself.For the general case, however, the hierarchical invocation mbody(m, I, J) finds "the most specific m above I and along path/branch J". "Along path J" additionally requires the result to relate to J, that is to say, the most specific interface that has a subtyping relationship with J.
In (T-Invk), as the compilation should not be aware of the dynamic type, it only requires that invoking m is valid for the static type of the receiver.The result of mbody contains the interface that provides the most specific implementation, the parameters and the return type.We use underscore for the return expression, matching both implemented and abstract methods. 3In Java the corresponding syntax is new I(){}.(T-New) is the typing rule for object creation new I().The auxiliary function canInstantiate(I) (see definition in Section 4.4) checks whether an interface I can be instantiated or not.Since fork inheritance accepts conflicting branches to coexist, the check requires that the most specific method is concrete for each method on each branch.
(T-Method) is more interesting since a method can either be an original method or a hierarchical overriding, though they share the same syntax and method typing rule.findOrigin(m, I, J) is a fundamental function, used to find "the most specific interfaces that are above I and along path J, and originally defines m" (see Section 4 for full definition).By "most specific interfaces", it implies that the inherited supertypes are excluded.Thus the condition findOrigin(m, I, J) = {J} indicates a characteristic of a hierarchical overriding: it must override an original method; the overriding is direct and there does not exist any other original method m in between.Then mbody(m, J, J) provides the type of the original method, so hierarchical overriding has to preserve the type.Finally the return expression is type-checked to be a subtype of the declared return type.For the definition of an original method, I equals J and the rule is straightforward.(T-AbsMethod) is a similar rule but works on abstract method declarations.
(T-Intf) defines the typing rule on interfaces.The first condition is obvious, namely, its methods need to be well checked.The third condition checks whether the overriding between original methods preserves typing.In this condition we again use some helper functions defined The second condition of (T-Intf) is more complex and is the key to type soundness.Unlike C++ which rejects on ambiguous calls, FHJ rejects on the definition of interfaces when they form a diamond.Consider the case when the second condition is broken: mbody(m, J, J) is defined but mbody(m, I, J) is undefined for some J and m.This indicates that m is available and unambiguous from the perspective of J, but is ambiguous to I on branch J.It means that there are multiple overriding paths of m from J to I, which form a diamond.Hence rejecting that case meets our expectation.Below is an example (Figure 3  Finally, rule (T-Anno) is the typing rule for a cast expression.By the rule, only upcasts are valid.

Small-step Semantics and Propagation
Figure 6 defines the small-step semantics and propagation rules of FHJ.When evaluating an expression, they are invoked and produce a single value in the end.

Semantic Rules
(S-Invk) is the only computation rule we need for method invocation.As a small-step rule and by congruence, it assumes that the receiver and the arguments are already values.Specifically, the receiver (J)new I() indicates the dynamic type I together with the static type J. Therefore mbody(m, I, J) carries out hierarchical dispatching, acquires the types, the return expression e 0 and the interface I 0 which provides the most specific method.Here we use e 0 to imply that the return expression is forced to be non-empty because it requires a concrete implementation.Now the rule reduces method invocation to e 0 with substitution.Parameters are substituted with arguments, and the this reference is substituted with the receiver, and in the meanwhile the static types are recorded via annotations.Finally, the return type I e is put in the front as an annotation.

Key Algorithms and Type-Soundness
In this section, we present the fundamental algorithms and auxiliary definitions used in our formalization and show that the resulting calculus is type sound.The functions presented in this section are the key components that implement our algorithm for method lookup.

The Method Lookup Algorithm in mbody
mbody(m, I d , I s ) denotes the method body lookup function.We use I d , I s , since mbody is usually invoked by a receiver of a method m, with its dynamic type I d and static type I s .Such a function returns the most specific method implementation.More accurately, mbody returns (J, I x x, I e e 0 ) where J is the found interface that contains the desired method; I x x are the parameters and its types, e 0 is the returned expression (empty for abstract methods).It considers both originally-defined methods and hierarchical overriding methods, so findOrigin and findOverride (see the definition in Section 4. To calculate mbody(m, I d , I s ), the invocation of findOrigin looks for the most specific original methods and their interfaces, and expects a singleton set, so as to achieve unambiguity.Furthermore, the invocation of findOverride also expects a unique and most specific hierarchical override.And finally the target method is returned.

Finding the Most Specific Origin: findOrigin
We proceed to give the definitions of two core functions that support method lookup, namely, findOrigin and findOverride.Generally, findOrigin(m, I, J) finds the set of most specific interfaces where m is originally defined.Interfaces in this set should be above interface I and along path J. Finally with prune (defined in Section 4.4) the overridden interfaces will be filtered out.

It originally defines m;
It is a supertype of I (including I); It is either a supertype or a subtype of J (including J); Any subtype of it does not belong to the same result set because of prune.

Finding the Most Specific Overriding: findOverride
The findOrigin function only focuses on original method implementations, where all the hierarchical overriding methods are omitted during that step.On the other hand, findOverride(m, I, J) has the assumption that J defines an original m, and this function tries to find the interfaces with the most specific implementations that hierarchically overrides such an m.Here I[m override J] is basically a direct lookup for method m in the body of I, where such a method overrides J (like static dispatch).The method can be either concrete or abstract, and the body of definition is returned.Notice that by our syntax, I[m override I] is looking for the originally-defined method m in I.

Definition of prune(set) :
• prune(set) = {I ∈ set | J ∈ set \ I, J <: I} The prune function takes a set of types, and filters out those that have subtypes in the same set.In the returned set, none of them has subtyping relation to one another, since all supertypes have been removed.(m, I, I) represents the set of branches that I inherits on method m.I can be instantiated if and only if for every branch, the most specific implementation is non-abstract.

Properties
We present the type soundness of the model by a few theorems below, following the standard technique of subject reduction and progress proposed by Wright and Felleisen [35].The proof, together with some lemmas, is presented in Appendix.Type soundness states that if an expression is well-typed, then after many reduction steps it must reduce to a value, and its annotation is the same as the static type of the original expression.Note that in Theorem 2, "#(x)" denotes the length of x.Our theorems are stricter than those of Featherweight Java [14].In FJ, subject reduction theorem states that after a step of reduction, the type of an expression may change to a subtype due to subtyping.However, in FHJ, the type remains unchanged because we keep track of the static types and use them for casting during reduction.
Finally we show that one-step evaluation is deterministic.This theorem is helpful to show that our model of multiple inheritance is not ambiguous (or non-deterministic).
Theorem 4 (Determinacy of One-Step Evaluation).If t → t and t → t , then t = t .

Discussion
In this section, we will discuss the design space and reflect about some of the design decisions of our work.We relate our language to traits, Java interfaces as well as other languages.Furthermore, we discuss ways to improve our work.

Abstract Methods
Abstract methods are one of the key features in most general OO languages.For example, Java interfaces (prior to Java 8) were designed to include only method declarations, and those abstract methods can be implemented in a class body.The formal Featherweight Java model [14] does not include abstract methods because of the orthogonality to the core calculus.In traits, a similar idea is to use keywords like "require" for abstract method declarations [28].Abstract methods provide a way to delay the implementations to future subtypes.Using overriding, they also help to "exclude" existing implementations.
In our formalized calculus, however, abstract methods are not a completely orthogonal feature.The canInstantiate function has to check whether an interface can be instantiated by looking at all the inherited branches and checking if each most specific method is concrete or not.
Our formalization has a simple form of abstract methods, which behave similarly to conventional methods with respect to conflicts.Other languages may behave differently.For instance, in Java 8 when putting two identical abstract methods together by multiple inheritance, there is no conflict error.In Figure 7, we use italic m to denote abstract methods.In both cases, the Java compiler accepts the definition of C and automatically merges the two inherited methods m into a single one.FHJ behaves differently from Java in both cases.In the fork inheritance case (left), C will have two distinct abstract methods corresponding to A.m and B.m.In the diamond inheritance case, the definition of C is rejected.There are two reasons for this difference in behaviour.methods as concrete methods with an empty body, and that simplifies the rules and proofs a lot.Secondly, and more importantly, we distinguish and treat differently conflicting methods, since they may represent different operations, even if they are abstract.Thus our model adopts a very conservative behavior rather than automatically merging methods by default (as done in many languages).Arguably, the diamond case it is actually an intentional conflict due to the same source T .Therefore our model conservatively rejects this case.It is possible to change our model to account for other behaviors for abstract methods, but we view this as a mostly orthogonal change to our work, and should not affect the essence of the model presented here.

Orthogonal & Non-Orthogonal Extensions
Our model is designed as a minimal calculus that focuses on resolving unintentional conflicts.Therefore, we have omitted a number of common orthogonal features including primitive types, assignments, method overloading, covariant method return types, static dispatch, and so on.Those features can, in principle, be modularly added to the model without breaking type soundness.For example, we present the additional syntax, typing and semantic rules of static invocation below as an extension: Expressions e ::= . . .| e.J 0 @J 1 :: m(e) Γ e 0 : I 0 I 0 <: J 0 Γ e : I I <: J Γ e 0 .J 0 @J 1 :: m(e) : A static invocation e.J 0 @J 1 :: m(e) aims at finding the method m in J 0 that hierarchically overrides J 1 , thus J 0 [m override J 1 ] is invoked.As shown in (S-StaticInvk), static dispatch needs a receiver for the substitution of the "this" reference, so as to provide the latest implementations.In fact, static dispatch is common in OO programming, as it provides a shortcut to the reuse of old implementation easily, and super calls can also rely on this feature.For convenience we just make it simple above, whereas in languages like C++ or Java, the static or super invocations are more flexible, as they can climb the class hierarchy.
One non-orthogonal extension to FHJ could be to generalize the model to allow multiple hierarchical method overriding, meaning that, we allow overriding methods to update multiple branches instead of only one branch.This feature offers a more fine-grained mechanism for merging and can be helpful to easily understand the structure of the hierarchy.Multiple overriding would be useful in the following situation, for example: • findOverride(m, J) = prune(overrides) with: overrides = {K | I <: K, K <: J and K[m override J] where J ∈ J With this approach, branches A and B are merged in the sense that they share the same code, which can be separately updated in future interfaces.Another approach would be to deeply merge the branches, with similar effect as introducing an intermediate interface AB to explicitly merge the two branches.However, this approach is problematic because there is no clear mechanism for identifying and further updating the merged branches.This could be an interesting future work to explore.
Other typical non-orthogonal extensions to FHJ could be to have fields.The design of FHJ can be viewed as a variant of Java 8 with default methods which allows for unintentional method conflicts.Like Java interfaces and traits, state is forbidden in FHJ.There are some inheritance models that also account for fields, such as C++ that uses virtual inheritance [10].In our model, however, we can perhaps borrow the idea of interface-based programming [33], which models state with abstract state operations.This can be realized by extending our current model with static methods and anonymous classes from Java.However such an extension requires more thought, so we leave it to future work.

Loosening the Model: Reject Early or Reject Later?
FHJ rejects the following case of diamond inheritance: Here both B.m and C.m override A.m, and D inherits both conflicting methods without an explicit override.In this case, automatically merging the two methods (to achieve diamond inheritance) is not possible, which is why many models (like traits and Java 8) reject such programs.Moreover, keeping the two method implementations in D is problematic.In essence, hierarchical information is not helpful to disambiguate later method calls, since the two methods share the same origin (A.m).Our calculus rejects such conflicts by the (T-Intf) rule, where D is considered to be ill-formed.We believe that rejecting D follows the principle of models traits and Java 8 interfaces, where the language/type-system is meant to alert the programmer for a possible conflict early.
Nonetheless, C++ accepts the definition of D, but forbids later upcasts from D to A because of ambiguity.Our language is more conservative on definitions of interfaces compared to C++, but on the upside, upcasts are not rejected.We could also loosen the model to accept definitions such as D, and perform ambiguity check on upcasts and other expressions.Then, we would need to handle more cases than C++ because of the complication caused by the hierarchical overriding feature.

Related Work
We describe related work in four parts.We first discuss mainstream popular multiple inheritance models and then some specific models (e.g., C++ and C#) which are closest to our work.Then we discuss related techniques used in SELF.Finally, we discuss the foundation and related work of our formalization.

Mainstream Multiple Inheritance Models
Multiple inheritance is a useful feature in object-oriented programming, although it is difficult to model and can cause various problems (e.g. the diamond problem [27,29]).There are many existing languages/models that support multiple inheritance [10,22,5,28,17,19,20,11,2].The mixin models [5,11,32,2,13] allow naming components that can be applied to various classes as reusable functionality units.However, the linearization (total ordering) of mixin inheritance cannot provide a satisfactory resolution in some cases and restricts the flexibility of mixin composition.Scala traits [22] are in fact linearized mixins and hence have the same problem as mixins.
Simplifying the mixins approach, traits [28,9] draw a strong line between units of reuse and object factories.Traits act as units of reuse, containing functionality code.Classes, on the other hand, are assembled from traits and act as object factories.Java 8 interfaces are closely related to traits: concrete method implementations are allowed (via the default keyword) inside interfaces, thus allowing for a restricted form of multiple inheritance.There are also proposals such as FeatherTrait Java [16] for extending Java with traits.Extensions [25,26] to the original trait model exists with various advanced features, such as renaming.As discussed in Section 2, the renaming feature gives a workaround to the unintentional method conflicts problem.However, it breaks structural subtyping.
Malayeri and Aldrich proposed a model CZ [17] which aims to do multiple inheritance without the diamond problem.Inheritance is divided into two concepts: inheritance dependency and implementation inheritance.Using a combination of requires and extends, a program with diamond inheritance is transformed to one without diamonds.Moreover, fields and multiple inheritance can coexist.However untangling inheritance also untangles the class structure.In CZ, not only the number of classes but also the class hierarchy complexity increases.

E C O O P 2 0 1 8 20:22 FHJ: A Formal Model for Hierarchical Dispatching and Overriding
The above-mentioned models/languages support multiple inheritance, focusing on diamond inheritance.They handle method conflicts in the same way, by simply disallowing two methods with the same signature from two different units to coexist.In contrast, our work provides mechanisms that allow methods with the same signatures, but different parents to coexist in a class.Disambiguation is possible in many cases by using both static and dynamic type information during method dispatching.In the cases where real ambiguity exists, FHJ's type system can reject interface definitions and/or method calls statically.

Resolving Unintentional Method Conflicts
A few language implementations have realized the problem of unintentional conflicts and provide some support for it.
C++ model.C++ supports a very flexible inheritance model.C++ allows the existence of unintentional conflicts and users may specify a hierarchical path via casts for disambiguation, as discussed in Section 2. With virtual methods, dynamic dispatch is used and the method lookup algorithm will find the most specific method definition.A contribution of our work is to provide a minimal formal model of hierarchical dispatching, whereas C++ can be viewed as a real-world implementation.There are several formalizations [34, 24,23] in the literature modeling various C++ features.However, as far as we know, there is no formal model that captures this aspect of the C++ method dispatching model.Apart from this, as discussed in Section 5.3, FHJ conservatively rejects some interface/class definitions that C++ accepts, and upcasts are never rejected since the ambiguity is prevented beforehand.
Although C++ supports hierarchical dispatching, it does not support hierarchical overriding.However, there are some possible workarounds that can mimic hierarchical overriding, including the MiddleMan approach4 , the interface classes pattern as described in Section 25.6 of [31], the LotterySimulation discussion in [30].Since these workarounds share the same spirit, we will discuss in detail the MiddleMan approach, with the code shown in Figure 8.In this example, classes A and B are two classes that both define a method with the same name m unintentionally.
Class MiddleMan, as its name suggests, acts as a middleman between its class C and its parents A, B. MiddleMan defines a virtual method m that overrides a parent method m and delegates the implementation to another method m_impl that takes this as a parameter.C++ supports method overloading, so that multiple m_impl methods with different parameter types can coexist.When defining class C, we specify the parents to be MiddleMan<A>, MiddleMan<B> instead of A, B. In this way, programmers may define new versions of A.m and B.m in class C by providing the corresponding m_impl methods.Then in the client code, the method call ((A*)c)->m() will print out the string "MA2", as expected.Although this workaround can help us defining partial method overrides to a certain extent, the drawbacks are obvious.Firstly, the approach is complex and requires the programmer to fully understand this approach.Moreover, the lack of direct syntax support makes MiddleMan code cumbersome to write.Finally, the approach is ad-hoc, meaning that the class MiddleMan shown in Figure 8 is not general enough to be used in other cases: more middlemen are needed if partial method overrides happen in other classes; and it is even worse when return types differ.C# explicit method implementations.Explicit method implementations is a special feature supported by C#.As described in C# documentation [19], a class that implements an interface can explicitly implement a member of that interface.When a member is explicitly implemented, it can only be accessed through an instance of the interface.Explicit interface implementations allow an interface to inherit multiple interfaces that share the same member names and give each interface member a separate implementation.
Explicit interface member implementations have two advantages.Firstly, they allow interface implementations to be excluded from the public interface of a class.This is particularly useful when a class implements an internal interface that is of no interest to a consumer of that class or struct.Secondly, they allow disambiguation of interface members with the same signature.However, there are two critical differences to FHJ: (1) default method implementations are not allowed in C# interfaces; (2) there is only one level of conflicting method implementations at the class that implements the multiple parent interfaces.Further overriding of those methods is not possible in subclasses.

Languages using hygienicity.
In NextGen/MixGen [1], HygJava [15] and Magda [3], hygienicity is proposed to deal with unintentional method conflicts.The idea is to give a method a unique identifier by prefixing the name with an unambiguous path.As shown in Figure 9, the prefix HelloWorld in the method call (new HelloWorld []).HelloWorld.MainMatter() is mandatory.So writing programs in these languages is tedious if not supported by a specialized IDE, that aids filling prefix/method information.The advantage of this approach, compared to ours, is that it does not require any additional notion for method dispatching.Indeed the compilation strategy is simple, just by generating conventional code (say in Java or C++) with method names attached with prefixes.Unfortunately, the disadvantage is that some expressive power is lost.In particular merging methods arising from diamond inheritance is not possible because the methods have different prefixes.As shown in Figure 10, two methods m from different branches A and B cannot be overridden by the method m in C because they are regarded as unrelated methods, and m in C is just another new method that has nothing to do with A.m or B.m.The reason is that in these hygienic approaches, path names are used to distinguish different methods.In contrast, our model can deal with unintentional conflicts, as well as merged methods because our semantics is not simply based on prefixing.Instead, our model keeps the names of methods unchanged, and our direct operational semantics takes static and dynamic type information into account at runtime when doing method dispatching.Finally, the multiple inheritance model in Magda is based on Mixins, whereas FHJ is based on traits.Thus, Magda inherits all limitations of Mixins (such as the linearization problem, etc).

Hierarchical Dispatch in SELF
As we have discussed before, although the mix of static and dynamic dispatch is particularly useful under certain circumstances, it has received little research attention.In the prototypebased language SELF [6], inheritance is a basic feature.SELF does not include classes but instead allows individual objects to inherit from (or delegate to) other objects.Although it is different from class-based languages, the multiple inheritance model is somewhat similar.The SELF language supports multiple (object) inheritance in a clever way.It not only develops the new inheritance relation with prioritized parents but also adopts sender path tiebreaker rule for method lookup.In SELF "if two slots with the same name are defined in equal-priority parents of the receiver, but only one of the parents is an ancestor or descendant of the object containing the method that is sending the message, then that parent's slot takes precedence over the over parent's slot".Similarly to our model, this sender path tiebreaker rule resolves ambiguities between unrelated slots.However, it is used in a prototype-based language setting and it does not support method hierarchical overriding as FHJ does.

Formalization Based on Featherweight Java
Featherweight Java (FJ) [14] is a minimal core calculus of the Java language, proposed by Igarashi et.al.There are many models built on Featherweight Java, including Feather-Trait [16], Featherweight defenders [12], Jx [21], Featherweight Scala [8], and so on.FJ provides the standard model of formalizing Java-like object-oriented languages and is easily extensible.In terms of formalization, the key novelty of our model is making use of various types (such as parameter types, method return types, etc) to track the static types as well as the dynamic types during reduction.As far as we know, this technique has not appeared in the literature before.This notion is of vital importance in our hierarchical dispatch algorithm, and it allows for a more precise subject-reduction theorem as discussed in Section 3.

Conclusion
This paper proposes FHJ as a formalized multiple inheritance model for unintentional method conflicts.Previous approaches either do not support unintentional method conflicts, thus have to compromise between code reuse and type safety, or do not fully support overriding in the presence of unintentional conflicts.To deal with unintentional method conflicts we introduce two key mechanisms: hierarchical dispatching and hierarchical overriding.Hierarchical dispatching is inspired by the mechanisms in C++.We provide a minimal formal model of hierarchical dispatching in FHJ.Such an algorithm makes use of both dynamic type information and static information from either upcasts or parameters' information.It not only offers code reuse and dynamic dispatch, but also ensures unambiguity using our hierarchical dispatching algorithm for method resolution.Additionally we introduce hierarchical overriding to allow conflicting methods in different branches to be individually overridden.FHJ is formalized following the style of Featherweight Java and proved to be sound.A prototype interpreter is implemented in Scala.We believe that the formalization of hierarchical dispatching features is general and can be safely embedded in other OO models, so as to have support for the fork inheritance.
Our model can certainly be improved in some aspects.As discussed in Section 5, there are orthogonal and non-orthogonal features that can potentially be added to the design space.The future work relates to loosening the model without giving up its soundness, together with more exploration on supporting fields in the multiple inheritance setting.

Figure 3
Figure 3 Examples in FHJ."m ↑ A" stands for hierarchical overriding "m override A".

Figure 5
Figure 5 Subtyping and Typing Rules of FHJ.
Model for Hierarchical Dispatching and Overridingin Section 4. I[m override I] is defined if I originally defines m, and canOverride(m, I, J) checks whether I.m has the same type as J.m. Generally the preservation of method type is required for any supertype J and any method m.
(e)) that illustrates the reason why this condition is needed:interface T { T m() override T { return new T(); } } interface A extends T { T m() override T { return new A(); } } interface B extends T { T m() override T { return new B(); } } interface C extends A, B {} ((T) new C()).m()Thisprogram does not compile on interface C, because of the second condition in (T-Intf), where I equals C and J equals T .By the algorithm, mbody(m, T, T ) will refer to T.m, but mbody(m, C, T ) is undefined, since both A.m and B.m are most specific to C along path T , which forms a diamond.The expression ((T) new C()).m() is one example of triggering ambiguity, but FHJ simply rejects the definition of C. To resolve the issue, the programmer needs to have an overriding method in C, to explicitly merge the conflicting ones.

(
C-Receiver), (C-Args) and (C-FReduce) are natural propagation rules on receivers, arguments, and cast-expressions, respectively.(C-StaticType) automatically adds an annotation I to the new object new I().(C-AnnoReduce) merges nested upcasts into a single upcast with the outermost type.

3 .
2 and Section 4.3) are both invoked.The formal definition gives the expected results for the earlier examples in Figure Definition of mbody(m, I d , I s ) : • mbody(m, I d , I s ) = (J, I x x, I e e 0 ) with: findOrigin(m, I d , I s ) = {I} findOverride(m, I d , I) = {J} J[m override I] = I e m(I x x) override I {return e 0 ; } • mbody(m, I d , I s ) = (J, I x x, I e ø) with: findOrigin(m, I d , I s ) = {I} findOverride(m, I d , I) = {J} J[m override I] = I e m(I x x) override I ;
Formally, Definition of findOverride(m, I, J) : • findOverride(m, I, J) = prune(overrides) with: overrides = {K | I <: K, K <: J and K[m override J] is defined By the definition, an interface belongs to findOverride(m, I, J) if and only if: it is between I and J (including I, J); it hierarchically overrides J.m; any subtype of it does not belong to the same set.Below we give other minor definitions of the auxiliary functions that are used in previous sections.Definition of I[m override J] : • I[m override J] = I e m(I x x) override J {return e 0 ; } with: interface I extends I {I e m(I x x) override J {return e 0 ; } . ..} • I[m override J] = I e m(I x x) override J ; with: interface I extends I {I e m(I x x) override J ; . ..} Definition of canOverride(m, I, J) : • canOverride(m, I, J) holds iff: I[m override I] = I e m(I x x) override I . . .J[m override J] = I e m(I x y) override J . . .canOverride just checks that two original m in I and J have the same type.Definition of canInstantiate(I) : • canInstantiate(I) holds iff: ∀m, ∀J ∈ findOrigin(m, I, I), findOverride(m, I, J) = {K}, and K[m override J] = I e m(I x x) override J {return e 0 ; } canInstantiate(I) checks whether interface I can be instantiated by the keyword new.findOrigin

Theorem 1 ( 2 (Theorem 3 (
Subject Reduction).If Γ e : I and e → e , then Γ e : I.Proof.See Appendix A.1.Progress).Suppose e is a well-typed expression, if e includes ((J)new I()) .m(v)as a sub-expression, then mbody(m, I, J) = (I 0 , I x x, I e e 0 ) and #(x) = #(v) for some I 0 , I x , x, I e and e 0 .Proof.See Appendix A.1.Type Soundness).If ø e : I and e → * e with e a normal form, then e is a value v with ø v : I.Proof.Immediate from Theorem 1 and Theorem 2.

Figure 7
Figure 7 Fork inheritance (left) and diamond inheritance (right) on abstract methods.
Model for Hierarchical Dispatching and Overriding interface A { void m() {...} } interface B { void m() {...} } interface C { void m() {...} } interface D extends A, B, C { void m() override A,B {...} // overrides branches A and B only void m() override C {...} // overrides branch C }Here D inherits from three interfaces A, B, C with conflicting methods m, but only merges two of those methods.While we can simulate D without multiple overriding in our calculus (by introducing an intermediate class), a better approach would be to support multiple overriding natively.We present the modification of syntax, typing and semantic rules below (abstract methods omitted):Methods M ::= . . .| I m(I x x) override J {return e; } (T-MoMethod) ∀J i ∈ J, I <: J i findOrigin(m, I, J i ) = {J i } mbody(m, J i , J i ) = (K, I x x, I e _) x : I x , this : I e 0 : I 0 I 0 <: I e I e m(I x x) override J {return e 0 ; } OK IN I Semantic rules themselves remain unchanged, however, we need to change slightly the definition of findOverride in mbody: Definition of findOverride(m, I, J) : interface A { void m() {...} } interface B extends A { void m() {...} } interface C extends A { void m() {...} } interface D extends B, C {} Y. Wang, H. Zhang, B. C. d. S. Oliveira, and M. Servetto 20:21

Figure 9 Figure 10
Figure 9Full-qualified name of method calls in Magda.

0 1 8 20:4 FHJ: A Formal Model for Hierarchical Dispatching and Overriding FHJ: a
formalized model based on Featherweight Java, supporting the above features.We provide the static and dynamic semantics and prove the type soundness of the model.Prototype implementation 2 : a simple implementation of FHJ interpreter in Scala.The implementation can type-check and run variants of all the examples shown in this paper.
E C O O P 2

this.shuffle(); this.draw(); } }
Here shuffleAndDraw invokes draw from its own enclosing type.In FHJ, this invocation is dynamically dispatched.This is important, because a programmer may define a subtype of Deck and override the method draw:
(middle), we define a new component DrawableRect that extends Drawable, which simply draws the deck as a rectangle, and modifies the hierarchy: } } interface DrawableSafeDeck extends DrawableRect, SafeDeck {} The MiddleMan approach.