KJR Universe (V2)

New features and limitations on interfaces and abstract classes

Interfaces, abstract classes, and assignments have been added to Karel Universe. Ordinary methods and constructors may also have parameters now. Non-robot classes have been added as well (superclass Object, rather than UrRobot).

There are a few restrictions, however, as Karel Universe does not implement all of Java. This is partly to keep the user interface as simple and spare as possible.

But it now has enough to do nearly all of Chapter 4 (sans Enumerations and casting).

A class here can only implement one interface (or none, of course)
An interface can only extend one interface
Interfaces have only abstract methods (no constants)
Classes can have only one constructor
While object-valued parameters have been added, object-valued return types have not been.

The above are sufficient for purposes of the book and so are unlikely to be extended.

Methods (and predicates) can now have (object valued) parameters. To add a parameter, first create the method in the usual way (dragging.) Then option-double click on the method's header. You will be asked to choose a type and a name for a new parameter. Do it again to add another. If you click without the option key you will get to edit the name of the method, the names of its parameters, and also delete parameters. There is no way to change the type of an existing parameter, other than deleting the parameter and adding a new one. Note that new parameters are always added at the end of the list of current ones. Note that if you have invoked a method and then change its parameter structure the previous invocation is illegal. You will get compile errors until you fix it.

The only valid return types are still just void and boolean. Object return types have not been implemented. This and the absence of Enumerations makes it impossible to do Section 4.7 with this system.

You can now add additional parameters to constructors. You can also add additional statements.This makes it possible to initialize an object completely in the constructor with arguments provided when the robot is created. Objects should be completely initialized in their constructors. The way to add/change parameters in constructors is the same as for ordinary methods, except that the required parameters (street, ...) of robots can not be removed or renamed.

When you drag a message icon into the program, you will be prompted for any needed arguments if it has parameters. Note that the pop ups show all the objects, not just the ones compatible with the parameter type. So you can create errors here. Each popup will show the type required of the argument, though. It isn't possible to dismiss this dialog without any effect (as it wouldn't make sense).

One option in the assignment statement dialog is "New Robot" for the right hand side. Choose this and you will get a dialog similar to that of initialization. You must also choose a class for the new robot from the choice popup. If the class constructor has additional parameters you will get a second dialog box to supply the matching arguments. You can also create new simple (non-robot) objects, such as strategies, in a similar way.

Primitive data, such as int, has not been added (and will not be). The only parameters and fields are objects and so all assignment is reference assignment.

When you define a new class you can choose its "kind" (ordinary, abstract, interface). If you choose interface, the superclass drop-down is still there, but won't be used. If you don't want the new class to implement any interface, leave the interface drop-down to "None". If you choose to create an interface and also "implement" an interface, the new one created will "extend" the original one as is correct for Java. This will be automatic, though the wording in the dialog won't change.

Interface types and abstract class types show up in the class tree as usual. If you drag one of these into the code window you get a declaration with null initialization. Class java.lang.Object also behaves this way, though it is really a concrete class. Also, if you drag in a type icon for a concrete class, the initialization dialog has a "Declare Only" option. If you hit this button, only the type and name will be used to declare a reference and give it a null initialization.

There is no way to add or delete an implemented interface (or change a parent class) from an existing class (other then editing the .r file by hand without error). You have to abandon the class and start over. If you don't want it to appear anymore, you have to manually edit its entry in the classes property of the project's vkp file. This is within the project directory on the disk.

When you drag in an abstract class or interface icon, you get just a declaration with a null initialization. To initialize, use (for example) an assignment with the new Robot option or an existing robot. It is possible to make some errors as you go along, including null pointer exceptions.

You can try to send a message via a robot reference that has not been initialized (if it is defined to have an abstract/interface type). This is just Java, of course, but previously we could guarantee all references were valid. If you try to send a message via a null reference, you will get a null pointer exception as usual. Since you want to see these messages, I suggest that you start the system from a command/terminal window that you leave open while the program runs. You will see the messages in this window. Otherwise, they will show up on the system console.

Assignment doesn't guarantee that the left and right sides are compatible. If you get a compile error you can fix it by double clicking on the assignment. You can also delete the assignment statement and start over.

The system attempts to add method stubs for new (concrete) classes that implement an interface (or extend an abstract class). If you add an abstract method to an interface or abstract class after creating concrete subclasses, the method stubs for the new method won't be added to the subclasses/implementing classes. You need to do this yourself. Until you do you will see severe errors in the command window.

Note that we now mark all of the fields private. In version one they were implicitly private (there was no way to refer to them from outside the class) but they weren't so marked. The Java code generated does mark all methods public and all fields private. You will also see public/private visibility markers if you choose to show Java syntax in the code windows (choice at startup).

All of the fields of a class appear at the bottom of the class definition. Private things should really go last anyway.

If you start this program fresh on a new system from some distribution, and there are no "class" files for the project, then you will get a lot of error messages. A second (occasionally third) startup without changing anything tries very hard to solve the problem and you should get a good start, but perhaps with lots of messages. While Java doesn't have "declare before use" rules in general, this system does have some, so circular dependencies cause it a lot of trouble. If you find a situation that doesn't work on the second or third try, I'd like to see it to see if I can do a better job with this. Send me all of the ".r" files in the project.

If you close the assignment dialog, rather than hitting one of its buttons, you get an illegal java statement (null = null;). You can undo this, or delete it. You can also double-click the assignment and choose the references differently.

While I believe that chapter 4 is the truly essential one, hence my work here, if you don't intend to teach it, then the first version of this is simpler and adequate for your needs. If you start with that one, for the first three chapters, and then take up this one, your students may be happier. The original has fewer options, has an identical look and feel where they overlap, but it is much harder to create an illegal program with it. I will publish both of these for the foreseeable future.

There is actually a startup option in the opening dialog that restricts this version to the features exposed in the first version. The default is to expose all the new features, however. Note that even if you restrict to the simple features, it will write files consistent with the complex features so that you can change at any time. The first version file formats are different and inconsistent with this version. I can show you how to translate the older files to the new, but it is a simple manual transformation. If you are clever with grep like tools you could automate it, actually. Normally only three lines need to be added to an old ".r" file to make it compatible with this version (an empty constructor at the very top of the class definition, just after the opening brace).

Casting has not been implemented, so the code on Pg 89 can't be created. You can think of this as a flaw or, better, think of it as an opportunity to teach better Java. A reference of interface type (or abstract class type should only be sent messages defined in the class or interface that declared it. I.e. "casting considered harmful."

When you start the program, there is a command line option that you may use. If you give a full path to a directory on your machine all of the user files will be stored there. This includes the all-important vk.properties file, which contains all of the known project information, as well as the projects directory, containing the user's project code. If you don't use this option, these files will be kept in the working directory. You can prime the directory pointed to with the necessary files, or it will create fresh copies, with only an empty 'default' project. Note the first console (and log) message after you start up will show you the directory that the program is using.

Notes on the files in the project directory: The system is driven by a set of files ending in extension ".r". These files are not Java, though they mostly look like Java. The correct formatting of these is essential to reloading a class on startup. Since things sometimes go bad, the .bak files are copies of the previous version of the .r files. These can occasionally save you from a serious program error. The program also creates real Java files and these are used by the runtime here, to create the corresponding .class files using an internal compiler. They may also be copied to another IDE so that you may preserve your work and extend it when you move on to a more complete system.