
Trait-oriented Programming in Java 8 Viviana Bono, Enrico Mensa, Marco Naddeo To cite this version: Viviana Bono, Enrico Mensa, Marco Naddeo. Trait-oriented Programming in Java 8. PPPJ’14: International Conference on Principles and Practices of Programming on the Java Platform: virtual machines, languages, and tools, Sep 2014, Cracow, Poland. hal-01026531 HAL Id: hal-01026531 https://hal.inria.fr/hal-01026531 Submitted on 22 Aug 2014 HAL is a multi-disciplinary open access L’archive ouverte pluridisciplinaire HAL, est archive for the deposit and dissemination of sci- destinée au dépôt et à la diffusion de documents entific research documents, whether they are pub- scientifiques de niveau recherche, publiés ou non, lished or not. The documents may come from émanant des établissements d’enseignement et de teaching and research institutions in France or recherche français ou étrangers, des laboratoires abroad, or from public or private research centers. publics ou privés. Trait-oriented Programming in Java 8 ∗ VivianaBono EnricoMensa MarcoNaddeo Dipartimento di Informatica, University of Torino, Italy {bono,naddeo}@di.unito.it, [email protected] Abstract elements in the collection. However, adding this method as ab- Java 8 was released recently. Along with lambda expressions, a new stract to Collection<T> interface would mean breaking back- language construct is introduced: default methods in interfaces. The ward compatibility: in other words, every old class implementing intent of this feature is to allow interfaces to be extended over Collection<T> interface would have to change by adding an im- time preserving backward compatibility. In this paper, we show plementation of forEach(LE), unless a default method is present a possible, different use of interfaces with default methods: we in the interface. Moreover, default methods may help avoiding code introduce a trait-oriented programming style based on an interface- duplication. as-trait idea, with the aim of improving code modularity. Starting In previous Java releases, interfaces were to provide multiple from the most common operators on traits, we introduce some type inheritance, in contrast to the class-based single implementa- programming patterns mimicking such operators and discuss this tion inheritance. Java 8 interfaces, instead, introduce a form of mul- approach. tiple implementation inheritance, too. Therefore, they are similar to traits [10], which are sets of (required and supplied) methods. 1 Categories and Subject Descriptors D.3.3 [Programming Lan- Java 8 interfaces, then, can be exploited to introduce a trait-oriented guages]: Language Constructs and Features programming style. Note that we are not proposing a linguistic ex- tension of Java 8 with traits, but programming patterns within Java Keywords Java 8, default method, trait, programming pattern, 8, with the goal of improving code modularity and, therefore, code code modularity. reuse. Starting from operators on traits [10], we introduce some Java 8 programming patterns mimicking such operators and dis- 1. Introduction cuss this approach. From the point of view of the language constructs, the most promi- The paper is organized as follows: Section 2 illustrates briefly nent addition in Java 8 is the lambda-expression construct, that the trait construct, Section 3 introduces Java 8 default methods, comes along with an apparently secondary construct, that is, the de- Section 4 proposes the programming patterns inspired by the trait fault method (aka virtual extension method, aka defender method) operators, Section 5 shows an example of use, Section 6 makes in interfaces. The primary intent of this feature is to allow interfaces some comparisons with related work, and Section 7 draws some to be extended over time preserving backward compatibility. These conclusions. features of Java 8 are described in the proposal JEP 126 (JDK En- hancement Proposal 126) Lambda Expressions & Virtual Exten- 2. What are traits? sions Methods [9]. JEP 126 is a follower of the Project Lambda, that corresponds to JSR 335 (Java Specification Request 335) [17]. The possibility of composition and decomposition of code are im- A default method is a virtual method that specifies a con- portant characteristics to care about in a programming language. crete implementation within an interface: if any class implement- Let us point out some problems of (single and multiple) inheritance ing the interface will override the method, the more specific im- concerning composability: plementation will be executed. But if the default method is not • Duplicated features. Single inheritance is the basic form of in- overridden, then the default implementation in the interface will heritance; thanks to that we can reuse a whole class (and also be executed. An already paradigmatic example of use of de- add some features). But sometimes we want to express some- fault methods to preserve backward compatibility concerns the thing that is much too complex to be implemented with single interface Collection<T>, already present in previous releases inheritance. For example, we could have a class Swimming (that of Java. Thanks to lambda expressions, now it is possible to in- gives features for swimming animals) and a class Flying (that troduce a forEach(LE) method that takes a lambda expression gives features for flying animals). What if we want to create an LE as an argument, coding a function to be applied to all of the animal that can both swim and fly, as swans? We can inherit ∗ only from Swimming or Flying but not both, so we will have This material is based upon work supported by MIUR PRIN Project CINA to duplicate some of the existing features in the Swan class. Prot. 2010LHT4KM and Ateneo/CSP Project SALT. • Inappropriate hierarchies. Instead of duplicating methods in the lower classes, we can bring those methods up in the hier- archy; however, this way we violate the semantics of the upper classes. • Conflicting features. If we have multiple inheritance (as C++ does) a common problem is how to treat conflicts. Method conflicts can be solved (for example, thanks to overriding), but [Copyright notice will appear here once ’preprint’ option is removed.] 1 This is pointed out in many places, see, for instance, [18]. 1 2014/7/22 conflicting attributes are more problematic. It is never clear if a 3. On default methods conflicting attribute should be inherited once or twice and how The role of an interface up to Java 7 was to give a contract to the these attributes should be initialized. user (that is, a type), but not to specify any detail of the contract it- self (that is, the implementation). The main characteristic of default Traits are a possible solution to these problems. A trait is a “simple methods (introduced by a keyword ) is that they are virtual conceptual model for structuring object-oriented programs” [10] default like all methods in Java, but they provide a default implementation and it is a collection of methods. This is very important: these traits within an interface. are statless, they cointain only methods, therefore every conflict of Java 8 method resolution is defined in [12] and its formalization state is avoided. Only method name conflicts must be dealt with, in a Featherweight-Java style [14] can be found in [13]. To summa- explicitly, by the programmer. rize it, we take the four (informal) rules about method linkage from Every trait can define required methods and required fields. In [13]: the considered model, required fields are indirectly modelled via required setter and getter methods. A trait can be defined directly • A method defined in a type takes precedence over methods (by specifying its methods) or by composing one or more traits. The defined in its supertypes. composition is performed by means of the following operators: • A method declaration (concrete or abstract) inherited from a • Symmetric Sum: a new trait is defined by combining two or superclass takes precedence over a default inherited from an more existing traits whose method sets are disjoint. In the case interface. the sets are not disjoint, conflicts arise. • More specific default-providing interfaces take precedence over • Trait overriding: a new trait is defined by adding method(s) to less specific ones. an existing trait. If an already present method is added, the old • Ifweareto link m() to a default method from an interface, there version is overridden. must be a unique most specific default-providing interface to • Exclusion: a new trait is defined by excluding a method from an link to, otherwise the compiler signals a conflict. existing trait. From these dispatch rules, we can extrapolate some examples of • Aliasing: a new trait is defined by adding a second name to a behaviour that can help the reader to understand the default method method from an existing trait. This is useful if the original name construct. was excluded after resolving a conflict. Note that, if a recursive A first example. If the class that implements the interface using method is aliased, the recursive call will be done on the original default methods does not override those methods, the default im- method. plementation provided in the interface will be executed. These operators are from the original proposal [10]. Other opera- interface A { default void m() tors were introduced in further works (a comprehensive list of op- {out.println("Hi, I’m interface A");} erators with relations among them can be found in [5]). We focus } on this particular set as we think they are the most interesting ones class B implements A {} from a programming point of view. //doesn’t override m The original definition of traits says that trait and class usages are separated: the first ones are units of reuse, while the second ones public class FirstDM { are generator of instances. A class can be specified by composing public static void main(String[] args) { a superclass with a set of traits and some glue methods (aka glue B b = new B (); code).
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages11 Page
-
File Size-