• Keine Ergebnisse gefunden

Reflection Patterns in the Context of Object and Component Technology

N/A
N/A
Protected

Academic year: 2022

Aktie "Reflection Patterns in the Context of Object and Component Technology"

Copied!
204
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Reflection Patterns in the Context of Object and Component Technology

vorgelegt von

Egbert Althammer

Dissertation zur Erlangung des akademischen Grades des Doktors der Naturwissenschaften (Dr. rer. nat.)

Vorgelegt an der Universität Konstanz Mathematisch-Naturwissenschaftliche Sektion Fachbereich Informatik und Informationswissenschaft

Konstanz, 2001

1. Gutachter: Prof. Dr. Wolfgang Pree, Universität Konstanz 2. Gutachter: Professor Dr. Mohammed Fayad, University of Nebraska

(2)
(3)

Summary

The thesis deals with reflection in the context of object technology and in the context of component technology. With object technology we in- tend the object paradigm and object-oriented concepts such as design patterns and frameworks; with component technology we intend the development and employment of software components. The expres- sion in the title, “reflection patterns”, describes the two central goals of the thesis and thus has two different meanings: first it means the en- hancement of existing patterns (the design patterns) with reflection and second it means the development of new patterns for reflection to facilitate the reuse of components.

The first part of the thesis discusses the theoretical foundations of reflection and sets the focus to Java and its reflective extensions.

The second part makes pragmatic considerations for the above de- noted issues by hands of concrete case studies. For the first issue which consists of the examination of the employment of reflection for design patterns and frameworks we obtain the following results: it can be proven that depending on the type of patterns that are used and on the way in which they are used, certain reflective techniques can be systematically employed.

The second issue which describes the employment of reflection in the realm of component technology is examined by hands of concrete case studies from projects of our group as well as existing applications in Java. The results are twofold: first we obtain general reflection guidelines which should guarantee the adequate employment of re- flection for concrete applications. They are developed by hands of the reflective implementation of the case studies using a checklist. Second, we obtain general reflection patterns which schematically describe the benefits of a reflective implementation of three relevant interaction types between components, mainly using semantic conventions.

(4)

Deutsche Zusammenfassung

Die Dissertation beschäftigt sich mit dem Thema Reflection, einerseits im Kontext von Objekttechnologie und andererseits im Kontext von Komponententechnologie. Mit Objekttechnologie sind dabei das Ob- jektparadigma und die objektorientierten Konzepte, wie Design Pat- terns und Frameworks gemeint, wohingegen Komponententechnolo- gie die Erstellung und den Einsatz von Software Komponenten um- fasst. Der Ausdruck im Titel „Reflection Patterns“ beschreibt die bei- den zentralen Ziele der Dissertation und ist im doppelten Sinne zu verstehen: es werden einerseits bestehende Patterns (die Design Pat- terns) mit Reflection verbessert und andererseits neue Patterns für Re- flection entwickelt, um die Wiederverwendung der Komponenten zu erleichtern.

Der erste Teil der Dissertation beschäftigt sich mit den theoreti- schen Grundlagen von Reflection, wobei der Fokus auf Java und seine reflexiven Spracherweiterungen gelegt wird.

Der zweite Teil stellt pragmatische Überlegungen zu den oben ge- nannten Punkten anhand von konkrete Fallstudien an. Der erste Punkt, der die systematische Untersuchung des Einsatzes von Reflec- tion für Design Patterns und Frameworks umfasst, bringt dabei die folgenden Ergebnisse: es kann nachgewiesen werden, dass abhängig vom Typ der angewandten Patterns und ihrer Anwendungsweise be- stimmte reflexive Techniken systematisch angewandt werden können.

Der zweite Punkt, der die Anwendung von Reflection im Bereich der Komponententechnologie beschreibt, wird anhand von konkreten Fallstudien aus Projekten des Lehrstuhls sowie aus bestehenden An- wendungen in Java untersucht. Die Ergebnisse sind zweifach, nämlich erstens allgemeine Reflection-Richtlinien, die einen adäquaten Einsatz von Reflection für konkrete Anwendungen garantieren sollen und die aus den reflexiven Implementierungen der Fallstudien anhand eines Fragenkataloges erarbeitet werden, und zweitens allgemeine Reflecti- on-Patterns, die die Vorteile einer reflexive Implementierung von drei relevanten Interaktionstypen zwischen Komponenten und Frame- works beschreiben, wobei der Einsatz von semantische Konventionen eine zentrale Rolle spielt.

(5)

Introduction

This thesis is the result of four years of theoretical and practical re- search in the realm of computational reflection at the Software Re- search group at the University of Konstanz.

The thesis is divided into two parts: the first part describes the theoretical foundations of reflection and its state-of-the-art. The sec- ond part describes how reflection enhances OO design patterns, frameworks and components.

The term computational reflection (or reflection) is defined as the activity of a computational systems when it models itself, thus makes explicit (= reifies) the elements of the language it is written in and the program currently executed. It might also alter these entities.

Although reflection has been studied since more than two decades, it has gained practical importance only in recent years: Java is the first commercial language which provides an application programming in- terface (API) for reflection (Reflection API). Before Java, only experi- mental languages used reflection, such as Common Lisp Object Sys- tem (CLOS) with the CLOS Meta Object Protocol (CLOS MOP).

The concrete applications of reflection are manifold. Generally speaking, reflective programming techniques are more flexible than non-reflective techniques: for instance, they allow more straightfor- ward component adaptations and thus they better support reuse. This is achieved through late binding and weaker typing. A recurring de- sign principle inherent in reflective systems is the coupling of compo- nents through semantic conventions. A potential drawback of reflec- tion, on the other hand, is the reduction of robustness and perform- ance of programs.

Chapter 1 explains the theoretical foundations of reflection for the ob- ject paradigm, makes a categorization and presents its state-of-the-art.

Chapter 2 describes three reflective languages, CLOS, Java and one of its reflective extensions, JavAssist. Chapter 3 describes how reflection improves the design patterns and framework construction principles.

Chapter 4 derives reflection guidelines which should guarantee the adequate employment of reflection for concrete applications. Chapter 5 rounds out the thesis by presenting reflection patterns which de- scribe the reflective implementation of three relevant types of frame- work-component interactions.

(6)

Danksagung

Mein besonderer Dank gilt Prof. Dr. Wolfgang Pree, der mich wäh- rend der vier Jahre der Dissertation begleitet hat. Seine Visionen und Ideen haben die Dissertation erst ermöglicht und auch zu ihrem Ent- stehen in der vorliegenden Form wesentlich beigetragen. Ebenso be- danke ich mich bei meinen Kollegen vom Lehrstuhl Sebastian Fisch- meister, Matthias Lampe, Guido Menkhaus, Thomas Obermüller, A- lessandro Pasetti sowie dem Hiwi Günther Hagleitner für die gute Zu- sammenarbeit bei den Projekten CACS und JGadgets und wertvolle Anregungen und Hinweise für die Dissertation. Weiters bedanke ich mich bei Fr. Mag. Engelen aus dem Fachbereich Philosophie für die Korrektur des Kapitels Reflection in Philosophy und bei Prof. Dr. Mo- hammed Fayad als Zweitgutachter der Dissertation.

Danke auch an meine Familie und Freunde, ohne die ich sicher nicht die Kraft gehabt hätte, die Dissertation fertigzustellen.

(7)

Table of Contents

Summary iii

Deutsche Zusammenfassung iv

Introduction v Danksagung vi

Table of Contents vii

PART I Theoretical Foundations of Reflection and State-of-the-Art 1

1 Reflection in Computer Science 3

1.1 Etymology of Reflection: Radices and Meanings in Various

Branches of Science 3

1.1.1 Overview of Reflection in Computer and Software Science 4

1.1.2 Reflection in Philosophy 5

1.1.3 Reflection in Language Grammar 7

1.1.4 Reflection in Mathematics 7

1.1.5 Reflection in Optics 7

1.1.6 Reflection in Physiognomy and Jurisprudence 9 1.2 Reflection Terminology in Software Systems 10

1.3 Reflection for the Object Paradigm 14

1.3.1 Reflection Models for the Object Paradigm 14 1.3.2 Reflection in Various OO Languages 16 1.3.3 Procedure-, Logic and Rule-Based Reflective

Architectures 18

1.4 Different Types of OO Reflection 18

1.4.1 Structural Reflection 19

1.4.2 Behavioral Reflection 20

1.5 Reflection at Different Stages of the Program Lifecycle 22

1.5.1 Compile-time Reflection 22

(8)

1.5.2 Load-time Reflection 23

1.5.3 Runtime Reflection 23

1.6 State-of-the-Art and History of Reflection 24 1.6.1 Further Reading and Current Sources of Interest 24 1.6.2 Objectives and Limits of Reflection 25 1.6.3 Historical Development of Reflection 26 2 Selected OO Reflective Architectures 27 2.1 Schema of the Description of a Reflective Architecture 27

2.2 CLOS 28

2.2.1 Overview 28

2.2.2 The Language Concepts 28

2.2.3 The CLOS MOP 33

2.2.4 Structural Reflection 34

2.2.5 Behavioral Reflection 37

2.3 Java 39

2.3.1 The Reflection API 39

2.3.2 Structural Reflection 40

2.3.3 Behavioral Reflection 45

2.4 JavAssist 49

2.4.1 The JavAssist MOP 49

2.4.2 Structural Reflection 50

2.4.3 Behavioral Reflection 56

2.5 A Comparison between CLOS, Java and Java + JavAssist 58

2.6 Other Reflective Java Extensions 58

2.6.1 Categorization of the Extensions 59 2.6.2 Extensions for Compile-time Reflection 60 2.6.3 Extensions for Load-Time Reflection 61 2.6.4 Extensions for Runtime Reflection 62 2.7 Reflective Programming Techniques in Java 64

2.7.1 Reflective Access to Objects 64

(9)

2.7.2 Abstract and Semantic Coupling 66 2.7.3 Method Parameters with Parameterized Types 67 PART II Application of Reflection in the Context of Frameworks, Design

Patterns and Components 69

3 Impact of Reflection on Frameworks and Design Patterns 71

3.1 Reuse-Related Terminology 71

3.1.1 Software Architecture 71

3.1.2 Reuse 71

3.1.3 Software Component 72

3.1.4 Framework 75

3.1.5 Design Patterns 77

3.2 Enhancement of Framework Patterns Through Reflection and Interfaces 82 3.2.1 Theoretical Discussion of the Effect of Reflection 83 3.2.2 Theoretical Discussion of the Effect of Interfaces 84 3.2.3 Schema of the Description of a FCP 85 3.3 Transformation of the Unification Principle 86

3.3.1 Structure 86

3.3.2 Example – Factory Method Pattern 88 3.4 Transformation of the Separation Principle 92

3.4.1 Structure 92

3.4.2 Example – Observer Pattern 94

3.5 Transformation of the Composite and Decorator Principle 99

3.5.1 Structure 100

3.5.2 Example – Composite 102

3.5.3 Example – Decorator 109

3.6 Transformation of the Chain-of-Responsibility Principle 110

3.6.1 Structure 110

3.6.2 Example – Chain-of-Responsibility 112

3.7 Summary 114

(10)

4 General Guidelines for the Use of Reflection 117 4.1 A Checklist for Applying Reflection 117 4.2 Evaluation of Systems Implemented with Reflection 119

4.2.1 Serialization 119

4.2.2 Java Beans 121

4.2.3 Transaction Management for EJBs 123

4.2.4 Jini 124

4.2.5 AspectJ 127

4.3 The Reflection Guidelines 128

5 Reflection Patterns for Component-Based Architectures 133

5.1 The Reflection Patterns 134

5.1.1 Schema of the Description of a Reflection Pattern 134 5.2 Reflection Pattern I – Framework-Component Interaction

(single) 135

5.2.1 Intention 135

5.2.2 Case Study 136

5.2.3 General Part 146

5.3 Reflection Pattern II – Component-Component Interaction 149

5.3.1 Intention 149

5.3.2 Case Study 150

5.3.3 General Part 159

5.4 Reflection Pattern III – Framework-Component Interaction (multiple) 165

5.4.1 Intention 165

5.4.2 Case Study 166

5.4.3 General Part 177

Index of Figures 181

Index of Tables 184

Index of Examples 185

Bibliographical References 187

(11)

PART I

Theoretical Foundations of

Reflection and State-of-the-Art

(12)
(13)

Chapter 1

Reflection in Computer Science

This chapter starts with a broader picture of reflection. It discusses the term reflection in various areas including philosophy, physics and com- puter science. It identifies the radices of the term and its meanings in those contexts and shows how they influence the formation of the term reflection in computer science.

The second part of the chapter introduces the basic terminology of reflection and its concepts for the object-oriented (OO) paradigm which is the scope of application of reflection in the realm of the the- sis. It provides a categorization of established reflective techniques and discusses the objectives and limits of reflection.

1.1 Etymology of Reflection: Radices and Meanings in Various Branches of Sci- ence

The term reflection and its related terms reflexive, reflex and reflective oc- cur in various branches of science. The meaning in the significantly differs depending on the particular field. Historically speaking, the scientific term reflection has been gradually adopted, starting with philosophy.

Reflection derives from the Latin reflectere which means to bend back something. The original translation serves as basis for the meaning of the scientific term reflection in the various fields:

• In computer science reflection is the part of a computational system which makes computations about the system itself.

• In philosophy, reflection forms the basic notion of the modern the- ory of cognition where only a critical view on the human mental activities guarantees an assured cognition.

(14)

• In language grammar, reflection is concerned with so-called reflec- tive verbs which express an action whose target is the subject itself.

Related to them are the reflective pronouns.

• In mathematics we speak of reflective relations. This is the case when each element is related with itself.

• In optics, reflection is the effect that light is thrown back when it is about to cross the boundary of two different materials such as air and water or glass (mirror effect).

• In physiognomy as well as in jurisprudence we speak of reflex movements and reflex actions. This has nothing to do with phi- losophical reflection; on the contrary, these are actions where no conscious brain activities are involved. It is related to the meaning in optics.

1.1.1 Overview of Reflection in Computer and Software Science

Reflection means that a computational system makes computations about its own system [Maes 88]. The visionary idea behind this is to introduce a kind of self-consciousness to a software system [Griffel 98]. This would presume that the computer is able to reflect about each action it performs as a human being.

Reflection in its current form is by far not able to do this. A system might reflect about the elements of a program and the programming language it is written in. Nevertheless, reflection is fundamental for the software area because it enables a series of revolutionary pro- gramming techniques to render programs more flexible, elegant and robust, which would be impossible or awkward without reflection.

The technical realization of reflection implies overheads. The main problems are performance and security and correctness issues, in par- ticular if the system alters itself by reflection. Although reflection has been studied in theory over more than two decades, it has been used in real-world systems only in recent years for several reasons: More processing resources compensate for the performance overheads.

Modern languages such as Java [Arnold et al. 00] and C# [Robinson et al. 01] support limited usage ed reflection.

(15)

1.1.2 Reflection in Philosophy

We summarize the philosophic formation of the concept of reflection of known philosophers which worked on that aspect. It is intended only as a very condensed overview of reflection. We refer interested readers to scientific lexicons, for example [Ritter, Eisler 92] which con- tains also further references.

The radices of reflection in philosophy go back to Plato and Aris- totle where they speak about “knowledge of knowledge” and “reason- ing about mind”.

Descartes and then Locke introduce the notion of reflection into phi- losophy as the opposite of sensation. While sensation as the external apprehension produces sensual matters (e.g. the things we see with our eyes), reflection represents as the internal apprehension the opera- tions of our own mind where also the idea belongs to. For them reflec- tion is a kind of introspection of the mind. The distinction they make is, though, problematic and has been solved by the introduction of tran- scendental reflection by I. Kant. G.W. Leibnitz views the capability of reflection as symptom of consciousness and uses the term logical reflec- tion.

Kant’s epochal writing “Critique of the Pure Reason”, in German:

“Kritik der reinen Vernunft” (KRV), discusses whether objective cog- nition is feasible, in science and in normal life. In order to proof how objective cognition can be done, a critical examination of the concepts of reflection has to be performed. These concepts are, for example, identity and disparity or determinability and destination. Kant intro- duces the term transcendental reflection to distinguish reflective acts from the fact that things may be perceived under different conditions (as phenomena) which is more exact than Locke’s distinction. The concept of experience (= empirical cognition) is central to Kant’s KRV.

It is the “ground” of cognition. Reflection is the means how the reason organizes its experience.

The critical examination can only be done if human’s rationality re- flects upon itself to find out its capabilities and limits. Hence, in this context the reason has a dual function: it is both the entity which per- forms the critical examination technique but is also subject to the criti- cal examination technique itself. This is possible because the reason is part of the consciousness which has a self-consciousness which allows reflection. With this mechanism the contents of the consciousness can be made conscious. For example, the statement “I think” is made con- scious by “I know that I think”.

(16)

Hegel continues the considerations of Kant. He provides a defini- tion of the purpose of philosophy. For him mind is the simple kind of reflection. Only reflection about reflection is the pure and rational way of thinking and this is what philosophy is about. He discerns the things as they are (with their properties to be distinguished from other things) and the way we perceive them (with our sense organs). Reflec- tion is everything that we perceive and what is not part of the thing it- self. Hegel further discusses the reflective analysis of abstract notions such as rational, true and false, good and beautiful.

According to Kant, a further competence of human reflection is the recognition of beauty in naturally beautiful things and art objects. This type of reflection is called aesthetic reflection and is related to what we understand as judgment of taste. In synthesis, the theory of aesthetic reflection expresses that when we recognize an object with its forms we have to abstract from all names and intentions to get the object in its pure vision. In our imagination we use our reflective capabilities, which is a sort of harmonic game of sensuality and rationality, to gain a subjective judgment of the object whether we find it aesthetic or ugly. Objects of art are judged by exactly this mechanism – they repre- sent a unity between form and aesthetic [Esser 97].

Last but not least we consider Schopenhauer who explores the the- ory of cognition and presents one of his most famous examples: the re- lationship between the world inside the head to the world outside (see Figure 1.1). The world inside the head consists of the perception of the world together with reflection about the world as well as reflection about mind itself. In this way he ties up to Kant. Schopenhauers con- siderations might lead to feedbacks between a person’s perception of the world and his or her acts. The famous short story of the hammer in [Watzlawik 83] humorously describes this.

Figure 1.1 Relationship between the world and the world inside the head

Overall, the term reflection originates in philosophy and the consid- erations which have been done in that area have influenced other dis-

(17)

ciplines of science. The meaning of reflection in computer and soft- ware science is closely related to its meaning in philosophy.

1.1.3 Reflection in Language Grammar

The grammar of a sentence consists of several parts: the subject, the verb, one or more objects and adverbs. The verb describes the action of the subject versus its targets represented by the objects. In case we want to express that the target is the subject itself we use so-called re- flective pronouns [Thieroff 00] such as oneself. In that case the verb is said to be reflective. In German and the roman languages there are a lot of such reflective verbs but in English there are only some such as to wash oneself. In German the reflective pronoun sich is common. In roman languages reflexive verbs are often used even when there is no reason to do so. For example, the Italian word for to get up is alzar-si.

The meaning of reflection in grammar is related to the meaning in computer science in the sense that the target of the action is the subject itself analogous to the target of the computations of the system being the system itself.

1.1.4 Reflection in Mathematics

In mathematics the term reflective is used in the context of mathemati- cal relations [Heuser 00]. For a given set M a relation ℜ ⊆ M × M is de- fined as the set of pairs of elements in M which are related to each other. For example if an element x ∈ M is related to another y ∈ M, it is expressed by (x, y) ∈ ℜ. We say that ℜ is reflective if each element is re- lated also to itself, thus that ∀ x ∈ M holds that (x, x) ∈ ℜ. This is true for example for identity, equality and ordering relations.

The meaning of reflection in mathematics is specific for mathe- matical relations and not related to the meaning of reflection in com- puter science.

1.1.5 Reflection in Optics

Objects [Feynman et al. 90] appear colored to our eyes because they throw back light with certain wavelengths when they are illuminated.

The sum of the beams of light which our eye perceives result in that color. A blue object, for example, is blue because it throws back the

(18)

wavelengths inside the blue wavelength region (between 450 and 500 nm). The other wavelengths are absorbed. This phenomenon of throw- ing back light is called reflection.

When a thin beam of light hits a smooth surface, another law of na- ture can be observed. There is an imaginary line that is drawn perpen- dicular to the surface at the point where the light strikes which is called a normal. Then the angle made by the normal and the incident ray (called the incidence angle) is equal to the angle made by the nor- mal and the reflected ray (the reflection angle). This fact is called the law of reflection. When light hits a smooth object, it bounces off much like billiard balls bounce off the side of a pool table: this is called specular reflection (see Figure 1.2a). When a beam of light hits a rough object, the same thing happens. As the surface is not flat, the incidence angle is different for each part of the beam so it is reflected in different directions: this is called diffuse reflection (see Figure 1.2b).

(a)

Specular Reflection Incident

angle Reflection angle

(b)

Diffuse Reflection

Figure 1.2 Reflection of a ray: (a) specular, (b) diffuse

An interesting effect is the one of total internal reflection (TIR) which occurs under certain conditions when a beam of light crosses the boundary of two media: if the light is in the more dense medium and approaching the less dense medium (for example water to air) and if the angle of incidence is greater than the so-called critical angle, the light does not cross the boundary but stays within the more dense medium. The light is reflected at the boundary according to the law of reflection. Figure 1.3 shows TIR at a glass lens. An online demo of this effect is found in [Kiselev 97].

Due to this property, light can be transported within glass fibers:

the light that enters the glass fiber in a certain incidence angle is re- flected on the margin of the glass with total reflection so that it makes a sort of zigzag through the fiber (where the angle remains constant)

(19)

and is transported over larger distances. Glass fibers are for example used to transport digitally encoded information.

Figure 1.3 Total internal reflection (adapted from [NCSU 00])

To sum up, the meaning of reflection in optics is that the beam of light is bended back. This is not related to the meaning of reflection in com- puter science.

1.1.6 Reflection in Physiognomy and Jurispru- dence

The term reflection in this context is used to describe so-called reflex actions [Della Porta 30]: remember the example when one bangs a small hammer on a certain point below the kneecap and suddenly the shank flips up. This immediate reaction which works without inter- vention of cognitive acts is called a reflex action. The term reflection is used here because the neural signal caused under the external influ- ence is conducted to the vertebral column or certain areas of the brain, elaborated and reflected to the muscles which carry out the reaction.

Reflex actions are behavioral patterns formed in early stages of human evolution and should protect human beings from sudden dangers. In jurisprudence reflex actions are treated separately because they do not cause a willful action to set an act. Such an act could be manslaughter caused by self-defense.

(20)

The meaning of reflection in physiognomy is again not related to reflection in computer science. Thus only reflection in philosophy and grammar are analogous to reflection in computer science.

1.2 Reflection Terminology in Software Sys- tems

This section defines important technical terms which are related to re- flection in computer science. We adopt the notions of the fundamental paper of Pattie Maes [Maes 87] which gives a survey of reflection, re- flective architectures and reflective languages. The paper of Jacques Malenfant [Malenfant et al. 96] discusses implementation issues re- garding reflection. For the following definitions both contributions have been considered.

To introduce reflection in the context of a software system the fol- lowing terms are used. We start by focusing on a computational sys- tem in general and its reflective counter part.

Definition 1.1 Computational System

A computational system is a system written in a particular programming language whose purpose is to answer questions about and/or support actions in some domain. A computational system is a program that must be executed by some kind of processor in order to perform com- putations.

A banking software system is thus a computational system about the banking domain. The domain of a computational system can be the system itself. In this case it is called a reflective system and its activity is called computational reflection (see Figure 1.4).

Definition 1.2 Reflective System and Computational Reflection A reflective system is a computational system whose domain is the sys- tem itself. Following Definition 1.1, it answers questions (= reflects) about itself and also may alter itself. More precisely speaking, it ob- serves and may change the structure of its elements and even the pro- gram language it is written in. This activity is called computational re- flection (or reflection for short).

(21)

Reflective System

Reflection (e.g. programs

and classes) pieces of software

Domain

Computational System

Figure 1.4 Computational system and reflective system

A computational system might contain such a reflective system. In this case some parts of the computational system belong to the reflective system and others do not. This leads to the definition of what a base and a meta system is. The distinction can then be made on the source code level as well.

Definition 1.3 Base System and Meta System, Functional and Non- Functional Code

A computational system which is about a domain and which contains a reflective system is conceptually divided into the base system and the meta system. The base system is the non-reflective part and contains the so-called functional code (with regard to the domain), which, for in- stance, does calculations, makes data base queries or opens GUIs. The meta system is the reflective part and contains the non-functional code (again with regard to the domain).

Hence, the meta system reflects about the base system. As a conse- quence, the meta system also reflects about the elements introduced by the meta system itself. Note that if the meta system alters the pro- gramming language it might cause feedbacks which have to be re- solved (see section 1.4.2). Note that the reflective system depicted in

(22)

Figure 1.4 can also be interpreted as a meta system while the computa- tional system is its base system.

The next definition characterizes a class of programming languages which recognize reflection as a fundamental programming task.

Definition 1.4 Reflective Architecture

A programming language is said to have a reflective architecture if it recognizes reflection as a fundamental programming task and thus provides tools for handling reflective computations explicitly.

The experimental language 3-KRS [Maes 87a] and Common Lisp Ob- ject System (CLOS) [Keene 89] are two examples for programming languages with a full-fledged reflective architecture. Java and C# have a reflective architecture which is significantly restricted because lan- guage alterations are considered to be potentially harmful. So reflec- tion forms a minor aspect of these languages.

Note that the base system needs not to be aware of the meta sys- tem. On the other hand, the base system gets information about itself only by invoking functions of the meta system.

The following definitions discuss the characteristics of computa- tional reflection in detail. We start with the fundamental definition of meta information.

Definition 1.5 Meta Information, Self-Representation

Meta information is information about the elements of the program- ming language. The meta information of all elements of a computa- tional system is called the self-representation of the system because it contains the information to (statically) describe the state of the system.

The meta information of a class, for example, consists of structural in- formation such as its name, its instance variables and methods, the corresponding qualifiers such as access rights, and behavioral infor- mation such as its storage allocation and the way how instances are created. The meta information of a method comprises pieces of infor- mation such as its signature and return type.

Since the meta information sufficiently describes the language ele- ments, it constitutes the interface of the language to computational re- flection in a natural way. Thus in order to perform reflection it is nec- essary that the reflective system makes the meta information accessi- ble to the program. This leads to the definition of reification and intro- spection.

(23)

Definition 1.6 Reification, Introspection

Reification is the process by which implicitly given meta information is brought to the fore using a suitable representation expressed in the language of the system in such a way that the user program can access it. The term introspection is used as a synonym for reification of ele- ments in OO programming languages and is in particular used within the Java community.

An important aspect of reification is whether there is a causal connec- tion between the reification data (in the meta system) and the related reified information (in the base system). A causal connection is man- datory for the meta system to bring modifications to the base system.

Definition 1.7 Causal Connection

A meta system is said to be causally connected to the base system if changes performed by the meta system are reflected in the base system and vice versa.

The causal connection has the effect that

• the self-representation of the base system is always up-to-date (base system meta system) and

• the meta system is able to bring modifications to the reified struc- tures of the base system (meta system base system).

Definition 1.8 Alteration

We denote the process that the meta system brings modifications to the base system as alteration. Note that this term is not a commonly used term in the literature on reflection.

Hence, to allow alteration the reflective architecture of a language and the runtime system must be causally connected. The realization of such a connection is not straightforward. A technique which allows the alteration of certain parts of the language is called interception.

This means that the meta system interrupts the program flow of the base system to execute the non-functional code. Interception is easier to realize and does not rely on causal connection.

Definition 1.9 Interception

Interception is the process of executing non-functional code of the meta system by interrupting the program flow of the base system. After the

(24)

execution of the non-functional code the program flow of the base sys- tem continues.

Figure 1.5 illustrates the three possibilities of reflection : with reifica- tion, alteration and interception. Reification and alteration require a causal connection.

Base system Meta system

Reification Alteration Interception

Figure 1.5 Reflective computation

1.3 Reflection for the Object Paradigm

Since the object paradigm is the most important paradigm, the thesis sets the focus on it. To complete the picture we mention also examples of reflective languages for other paradigms such as the procedural-, rule-, logic-based paradigms.

1.3.1 Reflection Models for the Object Paradigm

There are three reflection models which are described in [Ferber 89]:

• The Meta class model which is based on an equivalence between the meta object and the class of an object

(25)

• The Meta communication model which is based on the reification of a message

• The Meta object model where meta objects are instances of a class Metaobject or of one of its subclasses

Only the third model is used in today’s reflective architectures such as Java because it is the most flexible one. The meta object model requires an additional set of classes to store the meta information. They are called meta object classes and their instances meta objects.

Definition 1.10 Meta Object, Meta Object Class

Meta objects store the meta information of the elements of the computa- tional system. Meta objects are instances of special classes, the meta ob- ject classes.

Note that other authors such as [Keene 89] use the term meta class for meta object class.

Since the type of meta information is different for each language element, there is a separate meta object class for each element: class meta object class or method meta object class. We call these classes meta object classes because they are part of the meta system. Meta objects are accessed through a special API which is called the meta object pro- tocol (MOP) [Kiczales et al. 91]. It guards the correct relationship be- tween the objects of the base and the meta system. Figure 1.6 describes the relationship between the base class SampleClass and its meta object class which is called Class (example taken from Java). Its MOP consists only of the methods getName(), getFields() and getMethods() which are used to retrieve meta information about the class: its name, fields and methods, respectively. The base class accesses its meta object by invok- ing getClass(). Note that an object does not have its own meta object but uses the meta object of its class.

Class

name:String fields:Field[]

methods:Method[]

SampleClass m1():void m2():void getClass():Class

getName() returns the name of the class

Figure 1.6 Relationship between the base class and its meta object class

(26)

Definition 1.11 Meta Object Protocol (MOP)

The MOP defines the application programming interface (API) for the usage of meta objects and their classes.

The MOP for example defines a default meta object class for each ele- ment which reifies its structure and behavior. The MOP of CLOS [Kic- zales et al. 91] provides alteration by extending the default meta object classes (see also [Golm, Kleinöder 98]). The MOP of Java defines unal- terable default meta object classes and thus does not provide altera- tion.

1.3.2 Reflection in Various OO Languages

The major part of research efforts on reflection has been done in the realm of OO [Maes 87]. The reason for this is that reflection is a natural complement for the OO paradigm, in contrast to other paradigms such as procedure-based languages. Reflection is a means to describe typi- cal OO concepts such as inheritance: the super class(es) of a class be- come part of its meta information so that they are reified in its meta object which can be both accessed by the interpreter/runtime system ( method dispatch) and the program ( reification).

Reflection is further used to better modularize an OO system by fa- cilitating separation of concerns [Hürsch, Lopes 95] for example to specify persistence handling, concurrency, security aspects and distribution.

OO reflection has been developed in conjunction with OO pro- gramming languages, but the first reflective architectures emerged late (in 1986). In the first OO languages such as Smalltalk-72 [Goldberg, Kay 76] and Flavors [Weinreb, Moon 81] reflection is provided in an ad-hoc way: reflective information is not defined in meta objects but is intermingled with standard object information. This makes it difficult to extend reflective information and which leads to confusions. The next step has been done by the introduction of meta classes (meta class model) which serve as the classes of classes. Meta classes specify the internal structure and computation of a class. Languages such as Smalltalk-80 [Goldberg, Robson 83] make use of this concept. The problem remains that a class still mixes information about the domain and meta information. A further disadvantage is the disharmony be- tween the relationship of class and meta-class and of instance and class.

(27)

The next development step brings more uniformity into OO reflec- tion by representing each language element in terms of objects: classes, instances, meta class, instance variables, methods and messages. Ex- amples are languages such as Plasma [Smith, Hewitt 75] and ObjVLisp [Briot, Cointe 86]. The increased uniformity makes it possible to reflect on more aspects of an OO system.

The breakthrough of a language with a reflective architecture was the development of 3-KRS by Maes [Maes 87] which is an extension of KRS [Steels 86]. Maes sums up the crucial properties of a reflective ar- chitecture, which has not been realized before in an OO language.

1 Disciplined split between the base system and the meta system:

every element in the language is given a meta object which is causally connected.

2 The self-representation of the system must fulfill the following properties: uniformity (each element is an object), completeness (the meta object contains the whole meta information of the object), consistency (the meta information of one object is not contradictive to that of another one) and causal connection (to allow alterations at runtime).

After 3-KRS a series of reflective architectures emerges. CLOS which is an extension of Common Lisp has a reflective architecture whose MOP is called CLOS MOP. It is described in section 2.2. There is the ABCL (An object-Based Concurrent Language) family [Yonezawa 90] (with ABCL/R2 [Masuhara et al. 92] and ABCL/R3 [Masuhara et al. 94]) which enables reflective concurrent programming. ABCL/R2 intro- duces reflection for object groups to enable features such as group re- source management. ABCL/R3 enables highly optimized applications for parallel computers. A further notable language is CodA [McAffer 93] which has been designed for distributed systems. CodA uses the meta communication model to reify the basic components of message exchange (such as send, accept, queue, receive, protocol, execution and state). It can be used to implement different message-queuing policies.

OpenC++ [Chiba 96] is a reflective expansion for C++ [Stroustrup 97]

which relate to each other in an analogous way as as OpenJava relates to Java (see section 0).

Oberon [Mössenböck, Steindl 99] relies on the meta object model as well but does not keep the meta information in real objects but stores it in terms of structured sequences. The meta information is accessed using iterators which are called riders and which are part of the

(28)

Oberon Ref module. This model reduces memory consumption but has the disadvantage that the access to meta information requires sequen- tial parsing of the stream. The authors state that its cost is not time- critical.

Java has a reflective architecture whose MOP is called the Reflec- tion API. It is described in section 2.3. A series of reflective extensions such as OpenJava [Tatsubori, Chiba 98], JavAssist [Chiba 00] and MetaXa [Golm 97] enhance Java’s basic reflective capabilities. They are described in sections 2.4 and 2.6. C#, a language defined in the realm of Microsoft’s .NET advance [Platt 01] offers reflection mechanisms which are similar to those of Java.

1.3.3 Procedure-, Logic and Rule-Based Reflective Architectures

Procedure-based reflective architectures such as 3-Lisp [Smith 82] and BROWN [Friedmann, Wand 84] which are reflective variants of Lisp introduce the concept of a reflective function that manipulates the inter- preter data structures. For a discussion of reflective functions see also [Malenfant et al. 96]

There are logic-based reflective architectures such as FOL [Wey- hrauch 80] and META-PROLOG [Bowen 86]. META-PROLOG is a re- flective extension of Prolog [Clocksin, Mellish 84]. They introduce meta- theories to describe the logic deduction process itself.

Rule-based reflective architectures such as TEIRESIAS [Davis, Le- nat 82] and SOAR [Laird et al. 86] analogously introduce meta-rules which control the ongoing computation.

1.4 Different Types of OO Reflection

Within the object paradigm we categorize reflection by hands of two criteria. We discern between the reflection type: structural reflection and behavioral reflection [Ferber 89] and between the stage in program lifecycle reflection occurs: at compile-time, load-time or runtime [Golm 97], which is described in section 1.5. Figure 1.7 illustrates this categorization. A taxonomy of OO reflective languages according to

(29)

this categorization is found in [Kirby et al. 98]1. Note that in the re- mainder of the thesis we use the term reflection to denote OO reflec- tion.

reflection type class life cycle

run time

load time

compile time

behavioral structural

Figure 1.7 Categorization of reflection

1.4.1 Structural Reflection

Given a computational system and its underlying program, then struc- tural reflection is reflection about the program structure (for example, its classes) as well as the program currently executed (for example, its objects). Structural reflection reifies essentially what is specified in the source code of the program. We define structural reflection according to [Malenfant et al. 96]:

Definition 1.12 Structural Reflection

Structural reflection is concerned with the ability of the language to re- flect both about the structure of the program as well as the program currently executed.

1 The paper makes a third categorization into un-typed and strongly typed re- flection. Typed reflection means that results obtained by reflection have well specified types. Since we consider typed languages, we only will consider typed reflection.

(30)

Structural reflection is used for example to analyze a class for its in- stance variables and methods. Structural reflection can be as well used to create new classes, thus to extend a running program [Kirby et al.

98]. The author defines this application of structural reflection as the ability of a running program to generate new program fragments and to integrate these into its own execution. He uses the term linguistic re- flection as a synonym for structural reflection.

Structural alteration has to be implemented according to Maes’ cru- cial properties of reflective architectures discussed in section 1.3.2 to not make the base system unstable. Consider the case that the name of a class is changed. This has an influence on its instances which depend on that class definition as well as its subclasses.

1.4.2 Behavioral Reflection

With the behavior of an element of the language we denote its features which are predefined by the language definition as well as by the run- time system. They are normally unseen by the programmer. Let us consider a class method: while its structure is implemented in the pro- gram: its signature and body, its behavior is determined by the lan- guage definition: how the runtime system carries out the method dis- patch and whether the parameters are passed by value or by reference.

Behavioral reflection is concerned with the reification of the behavior of the elements. We define it according to [Malenfant et al. 96]:

Definition 1.13 Behavioral Reflection

Behavioral reflection is the ability of the programming language to re- flect about its own semantics and implementation as well as the data and implementation of the runtime system.

Behavioral alteration can be used to alter the programming language of the program. An example is the extension of a single-inheritance language to a multiple-inheritance language (see [Maes 87]). Another example is the change of the sequence of the super classes in multiple- inheritance languages (reported in [Kiczales et al. 91]).

Behavioral reflection at runtime leads to feedbacks if the interpreter which interprets the program is written in the same language as the base system, because it is also affected by the language alterations the meta system performs and thus the way it interprets the program changes. Such systems are called meta-circular. This may lead to incon- sistencies if updates made by the interpreter come in conflict with up-

(31)

dates made by the meta system. This problem is known as reflective overlap [Smith 82]. To solve this problem, a second interpreter is intro- duced to interpret the first interpreter. If the interpreter itself contains reflective code, we have to introduce a third interpreter and so on.

This leads to the potentially infinite reflective tower where the inter- preter In interprets the interpreter In-1 and the interpreter I1 interprets the program P (see Figure 1.8). In practice, the problem of infinity is solved by using a non-reflective interpreter written in another lan- guage which is on top of the reflective tower.

I nter pr eter I3 In t er pr et er I3 Inte rpre ter I3 Interpreter I3 I nt erpreter I3 Interpreter I3 Interpreter I3 Interpreter I3 Interpreter I3 Interpreter I3 Interpreter I3 Interpreter I3 Interpreter I3 Interpreter I3 Interpreter I3 Interpreter I3 Interpreter I3 Interpreter I3 Interpreter I3 Interpreter I3Interpreter I2Interpreter I2Interpreter I2Interpreter I2Interpreter I2Interpreter I2Interpreter I2Interpreter I2Interpreter I2Interpreter I2Interpreter I2Interpreter I2Interpreter I2Interpreter I2I nt erpreter I2Interpreter I2Inte rpre ter I2In t er pr et er I2I nter pr eter I2

Interpreter I2Interpreter I1Interpreter I1Interpreter I1Interpreter I1Interpreter I1Interpreter I1Interpreter I1Interpreter I1Interpreter I1Interpreter I1Interpreter I1Interpreter I1Interpreter I1Interpreter I1I nt erpreter I1Interpreter I1Inte rpre ter I1In t er pr et er I1I nter pr eter I1

Interpreter I1 Program

...

interprets interprets interprets

Figure 1.8 Reflective tower

Due to its nature, the implementation of behavioral reflection is more complex than that of structural reflection. Performed at runtime, it re- quires a MOP that reifies the language semantics and the runtime sys- tem. If it is causally connected, it potentially has to cope with the re- flective tower problem.

For many applications of behavioral reflection the alternative ap- proach of interception is sufficient. Note that interception does neither reify nor alter the language definition. Typical applications of inter- ception are extending method invocations, object instantiations and access to instance variables to enable a verbose mode or to check ac- cess rights.

(32)

1.5 Reflection at Different Stages of the Pro- gram Lifecycle

We discern between three major stages of the program lifecycle: com- pile-time, load-time and runtime2. Figure 1.9 illustrates the correspond- ing compile-time, load-time and runtime reflection.

Source code Byte code executable

class Class C ... {

...

}

coffeebabe

... 010100101

...

Runtime reflection JVM

Meta system

Load-time reflection Class loader

Meta system

Compile-time reflection Compiler

Meta system

Figure 1.9 Reflection at different stages of the program lifecycle

1.5.1 Compile-time Reflection

With compile-time reflection we intend reflective activities which are performed at compile-time, thus the reflection on the translation proc- ess of source code into binary format. According to Definition 1.3 the base system is the compiler.

Structural reflection at compile-time is used to enable multiple views on the source code such as class browsing, simple error checks, extraction of JavaDoc™ documentation and assembling the resulting GUI out of a GUI class. These applications are provided by many Inte- grated Development Environments (IDEs) for Java. Theoretically they are realized by reifying the compilation process. In practice they rely on a source code parser which is independent of the standard com- piler.

Behavioral reflection at compile-time is used to enable syntactical and semantic extensions of the basic programming language. Open- Java and Aspect-Oriented Programming (AOP) [Kiczales et al. 97] are two examples for that (see sections 2.6.2 and 4.2.5).

2 Depending on the particular programming language more or less cycles can be defined. For instance, purely interpreted languages lack the compile-time stage. This three phases are, in particular valid for the Java and C# program- ming languages.

(33)

Benefits and Drawbacks: a benefit of compile-time reflection is that it does not affect runtime performance because the overhead occurs at compile-time. A drawback is that only the static information of the language elements can be reflected. Also, to apply compile-time reflec- tion, access to the source code is necessary. Some IDEs de-compile the byte code first if the source code is not available in order to allow class browsing.

1.5.2 Load-time Reflection

With load-time reflection we intend reflective activities which are per- formed at load-time, thus the reflection about the process by which the program is loaded into the runtime environment. The base system is thus the program loader (or class loader in case of Java). Load-time re- flection is relevant in Java because it enables reflection about the run- ning program while at the same time avoiding the restrictions of real runtime reflection because the classes are not yet loaded into the JVM.

An example of load-time reflection is to dynamically add a field to an already compiled class. The reflective Java extension JavAssist enables load-time reflection for this purpose (see section 2.4).

Benefits and Drawbacks: a benefit of load-time reflection is that it op- erates on the byte code and thus it can be applied also for already de- livered components off the shelve (COTS), that is, software where as a rule the source code is not available. A drawback in respect to com- pile-time reflection is that runtime performance is affected when the code is loaded into the JVM.

1.5.3 Runtime Reflection

With runtime reflection we intend reflective activities which are per- formed at runtime about the program being executed, the language and the runtime system. Runtime reflection is the most comprehensive form of reflection where each part of the computational system is sub- ject to reflection. This flexibility requires, however, the solution of a series of technical problems. First there is the already mentioned prob- lem of meta-circularity. A second problem is the MOP and the reflec- tive architecture of the runtime environment. Implementing a reflec- tive architecture is a difficult task especially when performance plays a role. There is a lot of theoretic work which treats performance aspects

(34)

of runtime reflection (see [Malenfant et al. 96] for details). An impor- tant mechanism to enhance performance is partial evaluation which shifts actual binding times3 to earlier lifecycle stages where the costs of bindings are less harmful [Masuhara et al. 95]. A third problem is se- curity aspects of the runtime environment which can be undermined by runtime reflection [Golm, Kleinöder 98].

An example of a programming language which allows full-fledged runtime reflection is CLOS. Generally speaking, it can be stated that Lisp is better suited for reflection than Java due to its uniform syntax.

The Java extension MetaXa provides runtime behavioral reflection (see section 2.6.4).

Benefits and Drawbacks: the benefit of runtime reflection is that it is the most comprehensive and flexible type of reflection. A drawback is the overhead introduced by the reflective architecture of the runtime environment. If the architecture of the runtime environment limits runtime reflection due to performance and security reasons such as it is the case in Java, load-time reflection can be used instead.

1.6 State-of-the-Art and History of Reflection

This section concludes the discussion of reflection by discussing the state-of-the-art of reflection by presenting a commented literature list.

It further discusses the objectives and limits of reflection and summa- rizes the history of reflection.

1.6.1 Further Reading and Current Sources of In- terest

The following books and papers treat special topics on reflection and are worth considering for a deeper understanding of the concepts and applications of reflection. We briefly summarize their contents.

The Art of the Meta Object Protocol [Kiczales et al. 91]

3 The binding time is the time when the code is generated to for example in- voke a method. In OO languages with polymorphism we often have binding at runtime. Reflection might even further postpone the binding time.

(35)

The book describes the CLOS MOP and provides a comprehensive insight into the concepts and implementation of this full-fledged reflective architecture

Concepts and Experiments in Computational Reflection [Maes 87]

This paper presents fundamental definitions of technical terms for reflection and sketches the history of OO reflection. Further it de- scribes the features of the first reflective architecture 3-KRS

A Tutorial on Behavioral Reflection and its Implementation [Malenfant et al. 96]

This paper presents definitions of technical terms for reflection and discusses the implementation problems of behavioral reflection.

Load-time Structural Reflection in Java [Chiba 00]

This paper describes JavAssist, a reflective extension of Java and makes some critical comments about structural alteration.

Review about Computational Reflection [Tunes 01]

This Web site provides an overview about various topics and re- search on reflection.

There is a biennial conference about reflection. The proceedings of the first three conferences are available in [Kiczales 96a, Cointe 99, Yo- nezawa, Matsuoka 01].

A list of current sources of interest is described in [Malenfant et al.

96]. Some of the topics are

• Dynamic compilation

• Adaptive runtime systems

• Partial evaluation

• Binding-time analysis

• Extending reflection in Java

1.6.2 Objectives and Limits of Reflection

We discuss the objectives and limits of reflection separately for struc- tural and behavioral reflection since their realization is fundamentally different in concrete programming languages.

Structural reification is part of modern commercial languages such as Java and C# and has applications which range from enhancing ease of reusability of frameworks to automating type conversions. Struc- tural alteration further facilitates constructs such as class manipulation and code generation.

(36)

This augmentation of possibilities directly raises the question whether structural reflection can still guarantee error-free programs. It does if the language limits the reflective mechanisms to allow only se- cure constructs and further if the programmer uses structural reflec- tion in a proper manner. In the thesis both issues are discussed: section 2.4.2 considers restrictions for structural alteration and section 4.3 pro- vides guidelines for the proper use of structural reflection in concrete applications.

The application of behavioral reflection is of less practical relevance due to its complexity and security problems. That is the reason why languages such as Java and C# do not incorporate behavioral reflec- tion. Some Java extensions use interception and thus remain inside the limits of the language so that they can still rely on the built-in security mechanisms of Java (for details see sections 2.4 and 2.6). CLOS dem- onstrates the feasibility of behavioral reflection. It focuses on optimal performance.

1.6.3 Historical Development of Reflection

Table 1.1 summarizes the historical development of reflection and reflective architectures.

Table 1.1 Historical development of reflection Year Activities

1972 Development of the OO language Smalltalk-72 which uses reflec- tion in an ad-hoc way.

1980 Smalltalk-80 uses meta classes to store information about classes.

1982 Reflective languages for other language paradigms are developed, procedure based: 3-Lisp, logic-based: FOL and rule-based lan- guages: TEIRESIAS.

1987 Pattie Maes develops a language with a full-fledged reflective archi- tecture: 3-KRS.

1989 Ferber discerns between structural and behavioral reflection.

1991 Kiczales, Rivieres and Bobrow develop the CLOS MOP.

1992 –

1996 Design of reflective languages which address various aspects. The ABCL family which enables reflective concurrent programming.

CodA deals with the reflection on message-sending. OpenC++ de- fines a MOP for C++.

1995 Java Reflection API.

1998 – 2001

Development of reflective Java extensions such as OpenJava, As- pectJ, JavAssist and MetaXa.

(37)

Chapter 2

Selected OO Reflective Architectures

The previous chapter discussed the concepts and categories of compu- tational reflection. This chapter sketches representative sample OO re- flective architectures which use MOPs in order to show how reflection is realized in programming languages. The presented examples are the experimental language CLOS, the commercial language Java, and JavAssist, a reflective extension of Java for load-time reflection.

2.1 Schema of the Description of a Reflective Architecture

The description of the reflective architectures of the languages is or- ganized according to the structure presented in Table 2.1. This allows a comparison of the reflective architectures.

Table 2.1 Schema of the description of a reflective architecture

• Language overview

• MOP

• Structural reflection

o Reification of classes o Alteration of classes o Browsing classes o Reflection of instances

o Reflective creation of classes and instances

• Behavioral reflection

o Reification, alteration o Interception

(38)

2.2 CLOS

CLOS has a full-fledged and comprehensive reflective architecture which demonstrates the feasibility of realizing reflective concepts in a concrete language. To describe the MOP, we mainly rely on the book [Kiczales et al. 91].

2.2.1 Overview

CLOS is an OO language based on Lisp. It has been designed as a stan- dard extension to the non-OO language Common Lisp4 [Steele 90] and has been developed by the CLOS Working Group lead by Gregor Kiczales at the Xerox PARC. CLOS has been intended as an experi- mental language.

The following section provides a brief introduction of CLOS for which a profound knowledge of Lisp is not mandatory. For the inter- ested reader, we refer to [Kleene 89] for a detailed introduction to CLOS.

The OO structure of CLOS is simple and elegant. It follows the ba- sic ideas of Smalltalk-80. To explain the CLOS language elements we present their particular counterpart in Java if it exists. The most sig- nificant structural difference is the method dispatch mechanism.

2.2.2 The Language Concepts Classes and Instances

CLOS supports the class/instance paradigm which means that an ob- ject is always an instance of a class. A class defines the structure of its objects and contains the slots (= instance variables) and methods. A class is created with the function defclass and an instance is created with make-instance (see Example 2.1).

4 The goal has been to incrementally extend Common Lisp to an OO language in a conservative way: adding just the necessary OO constructs while being compatible to the original language.

(39)

Class Inheritance

Unlike Java, CLOS supports multiple-inheritance. Thus a class can have more than one super class5. The expression direct-super-classes provides the classes which the class directly inherits from (the variable direct-super-classes is a Lisp list). Note that an instance of a Java class invokes the method getSuperClass() of the corresponding Class in- stance to retrieve its super-class. CLOS further defines the variable class-precedence-list to denote all classes the class inherits from (more precisely speaking, it is the list of all super-classes of that class in a well defined order, including the class itself). In Java this expression is computed by a repeated call to getSuperClass(). CLOS explicitly speci- fies the subclasses of a class whereas Java does not. Note that this ex- pression is dynamic and is updated every time a subclass is newly cre- ated from that class. The CLOS class hierarchy has one root class which is called t. Its subclass standard-object is the parent class of all classes. The Java class hierarchy also has one root class which is called Object.

Slots

Slots correspond to Java instance variables and have a name, a value and attributes which characterize additional features of the slot. The attributes are denoted as keywords which have the prefix “:”. The attribute :initform specifies the default initial value for the slot, :initarg specifies the initialization keyword for the slot, :accessor specifies the access function for the slot. The presence of an access function denotes that the slot is public. It is analogous to the so-called setter- and getter- methods in Java. If no access function is defined, the function slot-value is used which denotes the private access of the slot. A slot is said to be unbound when it is not initialized and thus has no initial value. For unbound slots no storage is allocated. Assigning a value to a slot binds the slot and allocates the memory. CLOS offers two kinds of slots, local slots and shared slots which exactly correspond to the object and class variables of Java.

5 Java only allows multiple inheritance of interfaces.

(40)

Sample Class Hierarchy

Example 2.1 shows the definition of three sample CLOS classes. The first two classes, rectangle and color-mixin, directly inherit from stan- dard-object, whereas color-rectangle inherits from color-mixin and rectan- gle. The class rectangle represents a rectangle and has two slots, height and width whose initial values can be specified using the keywords :height and :width, respectively. Both are specified in :initarg. If no value is specified, both slots have the value 0.0, which is specified in :initform.

The class color-mixin is a class which is used to add color to other classes. It has three slots which correspond to the basic colors in the CMY-model (cyan, magenta and yellow).

The class color-rectangle inherits from rectangle and color-mixin. This class represents a rectangle with a specified color. It inherits all the slots from the super classes and adds one slot, clearp which denotes whether the rectangle is transparent. The y-or-n-p defines a prompt for yes or no. This slot has an access function which is called clearp.

Example 2.1 Sample class hierarchy in CLOS (adapted from [Kiczales 91]) (defclass rectangle ()

((height :initform 0.0 :initarg :height) (width :initform 0.0 :initarg :width))) (defclass color-mixin ()

((cyan :initform 0 :initarg :cyan) (magenta :initform 0 :initarg :magenta) (yellow :initform 0 :initarg :yellow))) (defclass color-rectangle (rectangle color-mixin)

((clearp :initform (y-or-n-p “But is it transparent?”) :initarg :clearp :accessor clearp)))

(setq door

(make-instance ‘color-rectangle

:width 38 :height 84 :cyan 60 :yellow 55 :clearp nil))

The last statement make-instance at the end creates an instance of color- rectangle and assigns it to the variable door using setq. The “’” before the name color-rectangle means that the expression is evaluated as a symbol (= string). The slots of door are initialized using the keywords specified in the :initarg attributes.

Referenzen

ÄHNLICHE DOKUMENTE

Pour faire évoluer la donne, il serait plus astucieux que les chaînes de valeur de la transformation de cette matière première en produits intermédiaires, au même titre que

The sub-humid sequence of altitudinal belts (example: Bagrot) is characterized by closed coni- ferous forests in the upper montane belt, which appear on shady slopes where the

Gleichermaßen kann folglich der Modus der "Richtigstellung" (ASBRAND & MARTENS 2020, §23) als Reaktion auf eine eben solche Reflexion der dokumentarischen

Adam Smith så ikke at aktiviteter med en sterk arbeidsdeling ville får større markedsmakt enn hans idealiserte jordbruk, selv om han forøvrig klart innså at arbeidsdelingen

In the reference study, which is based on a centralized supply chain, offgases from the HTL process are used as a feed for hydrogen production and anaerobic digestion (AD) is used

Policy making is messy based on imperfect understanding of the system and incentives, imperfect information of what others are doing.. That said, a common understanding of the

However, at least during the historical periods in Mesopotamia, ominous signs were indeed interpreted as divine revelations and insights into the intentions of

Klemm on his sixtieth birthday The phenomenon of electrotransport in a binary liquid alloy with perfectly miscible components is representable in terms of