Sections
Navigation
Running the Sample Application
Sample Application Development
API Specification
Hosted By
Inspired By
Copyright © 2002
The Feynman Project
Now that that we have a PhysicalObject, the next class that we need to develop is one that implements the PhysicalConfiguration interface. The main purpose of the Sample.java class is to provide the initial conditions of all of the PhysicalObjects in the PhysicalSystem of the simulation. The sample application only has a single CartesianObject so it must provide the initial conditions for the Ball in the CartesianSystem. Again we will leave out the JavaDoc for brevity in the source listings below. You can view the class Setup.java and read the source code.
import java.util.Iterator; import feynman.framework.system.PhysicalConfiguration; import feynman.framework.system.PhysicalSystem;Again we are just telling the compiler what classes we will need. The Iterator class in the java.util package is part of the Java Collections Framework. Again you can reference Learning Java for a complete understanding of the Collections Framework. For now just think of a collection of objects and the role of the Iterator is to provide a mechanism for obtaining references to the objects that are in the collection. The PhysicalConfiguration class is needed because we are extending it and the PhysicalSystem is the collection that the Iterator will use.
Notice in the class definition we are providing our implementation of the PhysicalConfiguration as well as creating instance variables of the type Ball and Iterator.
public class Setup implements PhysicalConfiguration { // ------------------------------------- instance variables. private Iterator i; private Ball b;Notice the use of the keyword implements instead of extends that was used in the Ball class definition. The reason is that PhysicalConfiguration is an interface and not an Abstract Class like the CartesianObject class is. Though there are always reasons for using each, when designing the Framework there is a simple rule that has been used. If there is anything that all sub-classes will share in common, then an Abstract Class is used since the sub-class will inherit the instance variable and methods. However, if there was nothing that could be shared or if the implementer is to have complete freedom on the implementation (ie meaning how to write the code), then an interface has been used.
For a CartesianObject, any sub-class of it will need and use its definition of the x, y and z instance variables and their corresponding getter and setter methods. The PhysicalConfiguration will be different for every single application that uses the Framework. It is extremely unlikely that any instance variables and code could be shared therefore it is defined as an interface.
The rest of the Setup class is shown below. Notice that it provides an implementation of the configure method as required by the PhysicalConfiguration interface.
public void configure(PhysicalSystem ps) { // Retrieve the reference to the particle from the physical system. i = ps.iterator(); b = (Ball) i.next(); // Setup its intial height and velocity. b.setY(0.0); b.setVy(10.0); }The argument to the configure method is a PhysicalSystem. Remember this is our collection and every collection can create an iterator that allows reference to all objects that are present in it. An Iterator is created and then used to retrieve the reference to our Ball object. Normally one would see a code fragment like the following
while(i.hasNext()) { b = (Ball) i.next(); }but since we only have a single object in our PhysicalSystem collection in the sample application, the while loop is not necessary.
Since the collection just contains PhysicalObjects, the reference to the Ball object must be cast into the correct type in order to access the methods specific to that object. Since Ball is lower on the class hierarchy than a PhysicalObject this is commonly referred to as Downcasting. Once the Ball has been properly referrenced, then its initial height and velocity are set using the appropriate setter methods. If the object retrieved from the Iterator had not been downcast, then an incompatible types error would occur because the instance variable b is of the type Ball. An example of the compilation error that is generated is shown below.
wbailey:/tmp/sample_app> ant Buildfile: build.xml prepare: build: [javac] Compiling 1 source file to /tmp/sample_app/classes [javac] /tmp/sample_app/src/Setup.java:32: incompatible types [javac] found : java.lang.Object [javac] required: Ball [javac] b = i.next(); [javac] ^ [javac] 1 error BUILD FAILED file:/tmp/sample_app/build.xml:32: Compile failed; see the compiler error output for details.The compiler tells you that it found a java.lang.Object and is requiring a Ball instead. One could have initially cast the b instance variable as a CartesianObject, but this would also cause a compilation error as shown below:
wbailey:/tmp/sample_app> ant Buildfile: build.xml prepare: build: [javac] Compiling 1 source file to /tmp/sample_app/classes [javac] /tmp/sample_app/src/Setup.java:37: cannot resolve symbol [javac] symbol : method setVy (double) [javac] location: class feynman.framework.system.CartesianObject [javac] b.setVy(10.0); [javac] ^ [javac] 1 error BUILD FAILED file:/tmp/sample_app/build.xml:32: Compile failed; see the compiler error output for details.This happens because the CartesianObject does not have any knowledge of a childs methods or instance variables. If you come accross compilation errors like the ones that have been demonstrated here, it is probably related to an improper or lack of a cast to the correct type.