REVERSE GENERICS Parametrization After the Fact
Total Page:16
File Type:pdf, Size:1020Kb
REVERSE GENERICS Parametrization after the Fact Alexandre Bergel PLEIAD Laboratory, Computer Science Department (DCC), University of Chile, Santiago, Chile Lorenzo Bettini Dipartimento di Informatica, Universit`adi Torino, Italy Keywords: Generic programming, Java generics, C++ templates. Abstract: By abstracting over types, generic programming enables one to write code that is independent from specific data type implementation. This style is supported by most mainstream languages, including C++ with tem- plates and Java with generics. If some code is not designed in a generic way from the start, a major effort is required to convert this code to use generic types. This conversion is manually realized which is known to be tedious and error-prone. We propose Reverse Generics, a general linguistic mechanism to define a generic class from a non-generic class. For a given set of types, a generic is formed by unbinding static dependencies contained in these types. This generalization and generic type instantiation may be done incrementally. This paper studies the possible application of this linguistic mechanism to C++ and Java and, in particular, it reviews limitations of Java generics against our proposal. 1 INTRODUCTION more than 100 down-casts and up-casts and 70 uses of instanceof. This examination reveals that in many The concept of generic programming (Dos Reis and places the amount of up-casting subsequent down- J¨arvi, 2005), which has characterized functional pro- casting that is used almost makes the programs be- gramming for several decades, appeared in main- have like dynamically typed code. stream programming object-oriented languages such Note, that the need to make existing code generic as C++, only in the late 80s, where it motivated from may arise also in languages where generic types were the beginning the design of the Standard Template Li- already available. In particular, either a library or brary (STL) (Musser and Stepanov, 1989; Musser and a framework is designed in a type parametric way Saini, 1996; Austern, 1998). Generic programming from the very beginning, or the “conversion” must be was not available in the first versions of Java, and this done manually, possibly breaking existing code. Sev- limited code reuse, by forcing programmers to resort eral proposals have been made that promote an auto- to unsafe operations, i.e., type casts. Generics are a matic conversion from non-generic code into generic feature of the Java 1.5 programming language. It en- code (Duggan, 1999; von Dincklage and Diwan, ables the creation of reusable parameterized classes 2004; Kiezun et al., 2007). These approaches involve while guaranteeing type safety. reverse-engineeringtechniques that infer the potential In spite of the limitations of Java generics, type type candidates to be turned into parameters. This pa- parameterization allows the programmer to get rid of per presents a different approach: instead of relying most type down-casts they were forced to use before on the programming environment to pick up type pa- Java generics; this also is reflected in part of the stan- rameters, a programmer may create a generic class dard Java library which is now generic. However, starting from a non-generic one, by using a proper much pre-1.5 Java code still needs to be upgraded to language construct. To our knowledge, no previous use generics. For example, a quick analysis on the attempt to offer a language built-in mechanism to gen- AWT Java library shows that some classes perform eralize classes has been proposed. 39 Bergel A. and Bettini L. (2009). REVERSE GENERICS - Parametrization after the Fact. In Proceedings of the 4th International Conference on Software and Data Technologies, pages 39-46 DOI: 10.5220/0002252700390046 Copyright c SciTePress ICSOFT 2009 - 4th International Conference on Software and Data Technologies We propose to extend the way generics are ex- ClassName>TypeName1, . , TypeNamen< pressed by defining a generic type (class or interface) The resulting generic class should then be as- from a non-generic type definition. Our approach signed to a class definition, which depends on the consists of an extension to be applied to an existing actual programming language (and in particular on object-oriented programming language. However, in its syntax for parameterized types); thus, in Java we this paper, we will investigate the possible applica- would write: tion of this extension to Java and C++. We will also demonstrate how the implementation of generic types class MyGenericClass<T extends TypeName> = > < in the language affects the usability of this new lin- ClassName TypeName ; guistic extension. With this extension, programmers In C++ we would instead write can create generic classes and interfaces starting from template<typename T> existing classes and interfaces by specifying the types class MyGenericClass<T> = that need to be turned into generic parameters. We ClassName>TypeName<; call this linguistic mechanism Reverse Generics. The class resulting from a reverse generic should This approach is different from the above men- be intended as a standard class in the underlying lan- tioned refactoring approaches since in our context guage. We could simply instantiate the type parame- there will be no refactored code: the starting class will ters of a generic class and then create an object, e.g., continue to exist after it is used to create its generic version. However, we believe that the refactoring new MyGenericClass<MyTypeName>(); techniques in the literature could formulate a refac- However, there might be cases (e.g., when using toring based on our reverse generics to actually im- partial instantiation, Section 2) where it is useful to plement the refactoring. simply instantiate a generic class and assign it another The paper is organized as follows. Section 2 class name; thus, we also consider this syntax: presents and illustrates Reverse Generics. Section 3 < > enumerates several typing issues due to the Java type class MyClass = MyGenericClass MyTypeName ; system with respect to generic programming. Sec- In the following, we informally describe and tion 4 presents briefly related work and Section 5 con- illustrate Reverse Generics with several examples cludes and presents future work. resulting from an experiment we conducted on the AWT graphical user interface Java library. The same mechanism may be applied to C++ templates. 2 REVERSE GENERICS Class Generalization. The class EventQueue is a Reverse Generics is an extension for object-oriented platform-independent class that queues events. It re- programming languages that enables a generic class lies on AWTEvent, the AWT definition of event. The to be created starting from an existing class, and a code below is an excerpt of the class EventQueue: generic interface from an existing interface. Some public class EventQueue { of the static type references contained in the original private synchronized AWTEvent getCurrentEventImpl() { class or interface are transformed into type parame- return (Thread.currentThread() == dispatchThread) ters in the resulting generic version. The process of ? ((AWTEvent)currentEvent.get()): null; } obtaining a generic class from a class definition is public AWTEvent getNextEvent() called generalization. We consider generalization as throws InterruptedException { the dual of the instantiation operation. We refer to un- ... binding a type when references of this type contained } in the original class definition are not contained in the public void postEvent(AWTEvent theEvent) { generic. ... boolean notifyID = (theEvent.getID() == this.waitForID); Given a class name, ClassName, and a type name, ... TypeName, the generic version of a class is denoted by } the following syntactic form: ... ClassName>TypeName< } All references to TypeName contained in the class In some situations, the EventQueue class may have ClassName are abstracted. A name is associated to the to be used with one kind of event, say KeyEvent. This abstract type in order to be concretized later on. Sev- will significantly reduce the number of runtime down- eral type names may be abstracted using the following casts and ensure type safety when such a queue has to writing: be used. 40 REVERSE GENERICS - Parametrization after the Fact By using reverse generics we can define the public interface GActionListener<T> = generic class GEventQueue<T extends AWTEvent> ActionListener>ActionEvent<; from the non-generic class EventQueue as follows: The benefit of this generalization is the ability to class GEventQueue<T extends AWTEvent> = reuse the interface ActionListener with a different event EventQueue>AWTEvent<; API. < > GEventQueue T extends AWTEvent is a generic Incremental Generalization. A generic class ob- definition of EventQueue that contains a particular data tained using reverse generics may be generalized fur- type, T. A type has to be provided to GEventQueue ther by unbinding other remaining static type refer- in order to form a complete class definition. To sat- ences. For instance, let us consider the class Event- isfy the Java type checker, a constraint has to be set DispatchThread, which is a package-private AWT class on T by enforcing it to be a subtype of AWTEvent. which takes events off the EventQueue and dispatches For example, in the method postEvent(...), getID() is them to the appropriate AWT components. Event- invoked on an event. The getID() method is defined DispatchThread is used in the EventQueue class as fol- in the class AWTEvent. Without the constraint