/* --- CSU213 Spring 2005 Lecture Notes --------- Copyright 2005 Viera K. Proulx Lecture 12: Mirror, mirror on the wall... or Java classes for Java classes */ /* Goals: - a case study to define the class hierarchy to represent a Java program Let us look at the following (incomplete) Java program: /* +----------+ | ALibItem | +----------+ +----------+ / \ --- | +--------------+ | Book | +--------------+ | String title | | int year | +--------------+ */ // to represent a library item abstract class ALibItem { } // to represent a book class Book extends ALibItem { String title; int year; Book(String title, int year) { this.title = title; this.year = year; } // determine whether this book was published before the given year boolean before(int year){ return this.year < year; } } class Examples{ Examples() {} Book b1 = new Book("HtDP", 2001); Book b2 = new Book("LPP", 1942); boolean testBefore1 = b1.before(1950) == false; boolean testBefore2 = b2.before(1950) == true; } /* Our goal is to define a class hierarchy that can represent the information recorded in this program. The first observation is that a Java program is a list of class definitions. Once we have made this observation, we look at the structure of class definitions. There are two kinds of classes: abstract and concrete. We put aside the consideration of absrtact classes for now and focus on the concrete classes. A concrete class has a name, several field definitions, a constructor, and some method declarations. We are beginning to see the structure of data and can write down the data definitions, first in the 'Scheme' style: A Program is a List of Class Definitions A Class Definition consists of --- name, which is a String --- superclass, the class that this class extends, which is again a Class --- constructor, - we will ignore for now --- fields, which is a List of Fields --- methods, which is a List of Methods Looking at field definitions it is clear what is the relevant information: A Field consists --- type, which is a Class --- name, which is a String The method definitions are a bit more complex: A Method consists of --- name, which is a String --- return type, which is a Class --- arguments, which (for now) is a List of Fields) --- body, which is a method Body - for now, yet another class of data... A Body consists of --- body, for now just represented by a String The following class diagram records all the information in the above semi-formal data definition: */ /* +--------------+ | ALoClassDefs |<----------------+ +--------------+ | +--------------+ | / \ | --- | | | ------------------------ | | | | +---------------+ +-------------------+ | | MTLoClassDefs | | ConsLoClassDefs | | +---------------+ +-------------------+ | +---------------+ +-| ClassDef first | | | | ALoClassDefs rest |----+ | +-------------------+ | | +----------------------------------------+ | | +--------------------------------+ | | | | | | v v v | | +-----------------------+ | | | ClassDef | | | +-----------------------+ | | | String name | | | | ClassDef superclass | | | +---------| ALoFieldDefs fields | | | | | ALoMethodDefs methods |--+ | | | +-----------------------+ | | | | | | | | v | | | +---------------+ | | | | ALoMethodDefs |<-------------+ | | | +---------------+ | | | | +---------------+ | | | | / \ | | | | --- | | | | | | | | | ------------------------- | | | | | | | | | | +----------------+ +--------------------+ | | | | | MTLoMethodDefs | | ConsLoMethodDefs | | | | | +----------------+ +--------------------+ | | | | +----------------+ +-| MethodDef first | | | | | | | ALoMethodDefs rest |--+ | | +--------------------+ | +--------------------+ | | | | | | | +---------------------+ | | | +--------------------------+ | | | | | | | | | v v | | | | +--------------+ | | | | | ALoFieldDefs |<------------------+ | | | | +--------------+ | | | | | +--------------+ | | | | | / \ | | | | | --- | | | | | | | | | | | -------------------------- | | | | | | | | | | | | +-------------------+ +-------------------+ | | | | | | MTLoFieldDefs | | ConsLoFieldDefs | | | | | | +-------------------+ +-------------------+ | | | | | +--| FieldDef first | | | | | | | | ALoFieldDefs rest |----+ | | | | +-------------+ +-------------------+ | | | | | | | | | | +--------------------------------------+ | | | | | +------------------------+ | | | | | | | | | v | | | | +------------------------+ | | | | | MethodDef | | | | | +------------------------+ | | | | | String name | | | | | | ClassDef returnType |------------------+ | | | | Body body |------------+ | | +----| ALoFieldDefs arguments | | | | +------------------------+ v | | +-------------+ | | | Body | | v +-------------+ | +---------------+ | String body | | | FieldDef | +-------------+ | +---------------+ | | ClassDef type |-----------------------------------------------+ | String name | +---------------+ */ /* We can actually write this as a Java program, but first we have to address a serious problem. The definition of a class requires that we identify the super class for every class, but does not provide any way of defining the class at the top of the class hierarchy. We also omitted the discussion of how abstract classes differ from concrete classes. To be able to write a working program, we make the class 'ClassDef' a subclass of AClassDef, and provide a variant DummyClassDef, that has only a name field. We will define two such classes, one to represent the class 'Object" and one to represent our abstract class 'LibItem'. We will also treat teh primitive types 'int', and 'boolean' as if they represented Java classes. With these modifications and restrictions we can now define Java class hierarchy that represents our example. The code is included in a separate file. Notice, that we have to reverse the order in which the data is defined, so we refer only to fields defined earlier. */ /* Once we represent the program this way, we can ask, how does the computer find the body of the method invoked by an object. In our example we have the method invocation b1.before(1050) and b2.before91950) b1 is a name of the field in the class Examples, and its type is Book. That means, the search for the method this object invokes starts in the class Book. In the list of methods, we indeed find the method 'before' and can inspect the argument list, to make sure it matched the argument list given at the invokation. If it does, we substitute the values of the arguments for their respective placeholders, and follow up with evaluating the body of the method. If the search fails in the class Book, we continue in its super class, climbing up the class hierarchy, till we have nowhere to go (reached the class Object, in a real Java environment). */