Learn Programming in Java

<<Previous | ToC | Next >>

Object-Oriented Programming (OOPS)

Java is an OOPS language, so most people who teach Java begin with OOPS. I'm here to teach you programming, and OOPS only to the extent that it helps you write Java. There is a section on OOPS in my "Things You Need to Know in Java" which is different from what this page tells you -- perhaps you will eventually want to read both -- but today you will learn enough about OOPS to write a game using my GameEngine. After you are comfortable writing games in Java (including within the GameEngine structure), you can Google "object oriented programming" and learn what I didn't tell you, but it isn't much and it won't make you a better programmer (just more knowledgeable).


You might be thinking, "If Tom is so down on OOPS, why teach Java?" Maybe "down on" is too strong, I think OOPS is a wonderful way to get certain kinds of type-safety that simply are not available any other way (see my explanation in "Things You Need to Know"), it's just that the promoters of OOPS have oversold their product. There is a lot of junk in OOPS (and in Java, even increasing) that should not be in a production language. Officially Java does not compile to machine language (although most implementations support a Just-in-Time ("JIT") native code recompiler that is almost as good as direct machine language), but this fact makes Java unusable for systems software, basically it lacks the generality of C.

This course is about Java because Java is the best programming language out there today with enough users to keep it alive and well. There are other languages out there with more users, but they are either untyped, or so weakly typed as to be useless. If you must use one of these other (dangerous) languages -- and the Real World is programmed in C, so that is a likely prospect -- think in Java while writing in C or Python, and your code will have fewer bugs and probably run faster. But you will think in Java only if Java is your "mother tongue" (the language you learned first).

That's why I teach Java.

OOPS Is Subroutines

OOPS is Subroutines writ large, nothing more or less. A subroutine is a collection of code and local data with a name, so it can be used to do a specific task from (almost) anywhere else in the program, without the programmer needing to think about how it is done. A class is a collection of code and local data with a name, so it can be used to do a specific task from (almost) anywhere else in the program, without the programmer needing to think about how it is done. Classes can (and usually do) also have included subroutines (called "methods" but they are just subroutines). In some older languages (not C, of which Java is a derivative) subroutines can also have included subroutines. Class variables do not vanish between invocations like subroutine data, but in some languages (C is one of them) the subroutines can keep their own private non-volatile data.

One important difference is that classes are data types, so you can have variables that refer to this particular collection of subroutines and data. That is useful because classes can be subclassed so that varibles defined to be of the type specified by the superclass (the parent class) can be assigned values that are references to a subclass, which -- and this is the important part -- the subclass can rewrite the subroutines, and calls to a subroutine in the superclass will actually call the corresponding subroutine in the subclass, if that is what the variable refers to.

This is easier to understand with a specific example. Let's define a

class Person {
  private String name;
  private int age;

  public String WhoAmI() {
    return name;}

  public String DoWhat() {
    if (age<18) return "student";
    return "?";}

  public Person(String nm, int old) { // constructor
    name = nm;
    age = old;}
} // end class Person

Then somewhere else in the program we can make variables of type Person:

Person Meg = new Person("Margaret",12);
Person Dad = new Person("John Smith",40);

Then somewhere else, we might print out

System.out.println(Meg.WhoAmI() + " is a " + Meg.DoWhat() + ".");
we get
Margaret is a student.

That's all fine and dandy, but the subclass makes it more interesting:

class Teacher extends Person {
  // private String name; // these are already included
  // private int age;
  private int degree;
  private String domain;

  public String WhoAmI() {
    if (degree>20) return "Dr."+super.WhoAmI();
    return super.WhoAmI();}

  public String DoWhat() {
    return "teacher";}

  public Teacher(String nm, int old, String major, int edu) { // const'r
    super(nm,old); // base class constructor makes the assignment
    domain = major;
    degree = edu;}
} // end class Teacher

Then we can change the creation of variable Dad

Person Dad = new Teacher("John Smith",40,"history",22);

Dad is still a Person, but he is now also a Teacher. So when we print out

System.out.println(Dad.WhoAmI() + " is a " + Dad.DoWhat() + ".");
we get
Dr.John Smith is a teacher.

The WhoAmI method in the subclass Teacher is said to override the same method in the base class Person., and even though the program that is printing out who John Smith is only knows he is a Person, the underlying OOPS mechanism knows he is a Teacher and gets the methods from the Teacher class.

Objects In GameEngine

This is now where the rubber hits the road. GameEngine specifies two classes that you must be concerned with. Actually three, but the other one is only a name, you don't actually do anything OOPSy with it, except that when you need to call a method you use the name.

Like Calculator, your game will be its own class, but it will be a subclass of the existing class GameEvent, which I defined as part of the GameEngine. That means all the methods I defined for GameEvent will already be methods of your game. So when the GameEngine wants to tell your game that the user clicked the mouse on one of the artifacts on the screen of your game, it will call the predefined method ClickEvt, and your game will know exactly what got clicked, and your code can respond to that event appropriately. OOPS does that for us. We could do it before, but it was really hard to do it safely unless everything was compiled together. Separate game engines (like mine) that outsiders (like you) could write games for did not, and could not, exist.

The other predefined class you will use a lot in your GameEngine game is GameWgt for specifying the visible artifacts ("widgets") the user sees on your game board (the game board itself is also a widget). There are several (internal) subclasses, but you do not need to think about them, only the base class GameWgt. Like Person in our example above, all the methods in the subclasses are available to the caller who needs only to think of it as a GameWgt. Mostly you won't even directly create widgets, you will define them in a tool I call "GameMaker" (which is also a subclass of GameEvent, running in the GameEngine) and the GameMaker will build a stub version of your game class, so that all you need to do is add (Java) code to make the game play. The widgets will already be there and the right color, and if you say so, they will already be moving, but your code decides what to do when they bump into something, or the user clicks somewhere, and so on. You will have given the interesting widgets names in GameMaker, and your code can access those widgets by name to move them around or change color or whatever. OOPS does that for us.

Programming the GameEngine involves a different way of thinking about your program. I call it "event-driven" (in the GameEngine) compared to "flat-file" (the way all your previous programs and games were). It's the difference between programming for people or programming for machines. People are not machines, but sometimes the machines don't know that. You can be better.

Next: Events

<<Previous | ToC | Next >>

Revised: 2020 October 27