Filters








1 Hit in 0.058 sec

DeepFJig — Modular composition of nested classes

Andrea Corradi, Marco Servetto, Elena Zucca
2012 Journal of Object Technology  
We present a new language design which smoothly integrates modular composition and nesting of Java-like classes. That is, inheritance has been replaced by an expressive set of composition operators, inspired by Bracha's Jigsaw framework, and these operators allow to manipulate (e.g., rename or duplicate) a nested class at any level of depth. Typing is nominal as characteristic of Java-like languages, so types are paths of the form outer n .C 1 . . . . .C k which, depending on the class (node)
more » ... the class (node) where they occur, denote another node in the nesting tree. However, paths denoting the same class are not equivalent, since they behave differently w.r.t. composition operators. The resulting language, called DEEPFJIG, obtains a great expressive power, allowing, e.g., to solve the expression problem, encode basic AOP mechanisms, and bring some refactoring techniques at the language level, while keeping a very simple semantics and type system which represent a natural extension for, say, a Java programmer. In this paper, we describe an extension of FJIG, called DEEPFJIG, where these composition operators have been generalized to manipulate nested classes. For instance, sum of two classes is hierarchical in the sense that nested classes with the same name are recursively summed, similarly to deep mixin composition [Ern99b, OZ05, Hut06] and family polymorphism [EOC06, IV07, ISV08], which, however, take an asymmetric approach. Analogously it is possible to rename or make an alias of a field, method, or a nested class itself, at any depth level. Typing is nominal as characteristic of Java-like languages, that is, types are (class) paths, which are sequences of the form outer n .C 1 . . . . .C k which, depending on the class (node) where they occur, denote another node in the nesting tree. However, class paths denoting the same class are not equivalent, since they behave differently w.r.t. composition operators. The resulting language offers a great expressive power, allowing, e.g., to solve the expression problem and to encode generics [BOSW98, GJSB05] and MyType [BOW98] . Moreover, since a whole program can be "packed" into a single class, also the basic AOP mechanisms can be expressed. Finally, the kind of code manipulation achieved by the composition operators corresponds to bring some refactoring techniques at the linguistic level. On the other hand, the generalization of the composition operators to the case with nesting is very natural and intuitive, and, more generally, the language keeps a simple semantics and type system which represent a natural extension for, say, a Java programmer. There are many other proposals allowing class nesting and, hence, some form of paths. Notably, among real world languages, Java and and C# support nested classes only as a way to achieve hierarchical organization. In such languages, as well as in Scala, the binding for nested classes is static, that is, redeclaring a nested class in a subclass has the effect of hiding the parent's nested class. On the other hand, in, e.g., gbeta [Ern99a] and Newspeak [BvdAB + 10], as in the literature on family polymorphism [Ern01, EOC06, ISV05, IV07, ISV08], a class can inherit from a virtual superclass, and this feature provides a great expressive power, at the price of making typechecking harder. Virtual superclasses can be emulated by C++ templates, as shown in the work on mixin layers [SB01]. In Scala, abstract types and traits can be used for a similar, but more involved, emulation. Our approach comes from a design principle rather different from all those mentioned above. That is, we replace inheritance by a true language of composition operators, mainly inspired by the seminal work in [Bra92] and its formalization as module calculus in [AZ02], and partly by the work on traits [SDNB03], notably the proposals which do not include inheritance [BDG07, BDG08]. In DEEPFJIG this design principle is "naturally" extended to handle nested modules (classes), and this enables us to use a type system without dependent types and without class families, but still powerful enough. This shows a particular trade-off in the language design space that has a number of useful properties, including better compatibility with the mainstream than proposals using dependent types. For what concerns our form of class paths, the closest work is likely [IV07], notably for the formalization aspects. A more detailed comparison with related work is provided in Section 4. The rest of the paper is organized as follows. In Section 1 we illustrate DEEPFJIG and its expressive power. In Section 2 we give the formal syntax and semantics, and in Section 3 the type system and the related results. In Section 4 we summarize the contribution of the paper and discuss related work, and in Section 5 we conclude outlining some further research directions. Proofs of results are in the Appendix. This paper is an improved and extended version of [CSZ10, CSZ11] . Notably, the full formalization of the semantics, the type system and the soundness results were not included in [CSZ11]. DEEPFJIG Modular composition of nested classes · 3 1 Examples We illustrate first, in Section 1.1, features which are inherited from FJIG, then we describe how to declare and refer to nested classes in Section 1.2, and in Section 1.3 the composition operators. Finally, in Section 1.4 we provide some more interesting examples which show the expressive power of the language. FJIG summary The following example shows three class declarations. The first two declarations look similar to Java class declarations. However, the syntax is slightly different, to stress that in FJIG and DEEPFJIG a class declaration just introduces a name for the expression occurring at the right of the equal symbol, which is called a class expression and denotes an unnamed class. See also Section 4 for more comments on this difference. In the first two declarations above, the class expression is a basic class, which is similar to a Java class body. In the third declaration, the class expression is the class name A, which denotes the first class, hence the declaration is equivalent, in a sense that will be made more precise in the last paragraph of this subsection, to the following one: C = abstract{ abstract int m1(); int m2(){return this.m1() + 1;} } Compound class expressions can be constructed using composition operators 1 . For instance, a new class can be defined by applying the sum operator to those above as follows: Sum = A [+] B This declaration is equivalent to the following: () { return 1; } int m2() { return this.m1() + 1; } } Conflicting definitions for the same field or method are not permitted, whereas abstract fields or methods with the same name are shared. The modifier abstract applies to fields as well, as shown by the following example which also illustrates how constructors work. The class declarations A1 = abstract{ abstract int f1; int f2; constructor(int x) { this.f2 = x; } int m() { return this.f1 + this.f2; } } B1 = { int f1; constructor(int x) { this.f1 = x + 1; } } [+] A1 are equivalent to 1 Each basic class plays the role of a constant (0-ary) composition operator, see the formal syntax in Figure 1 .
doi:10.5381/jot.2012.11.2.a1 fatcat:tveway6ysnha5igi645kjakqpq