Programming 1, fall 2007 -- Demonstration 7

This might not be complete or thorough enough... Always seek knowledge from textbooks! They tend to be quite complete... (I hope you have one available!)

Where I want everybody to be after demonstration 6:

Agenda for the next step:

First of all we complete our tool set:

Then, if we have time, we go a bit into Object Orientated Programming (OOP) and thinking. Not fully, but preliminarily:

Contents

Type system of Java extended: objects and references

Last time I mentioned that there are only eight kinds of primitive types. All data structures in Java boil down to objects that contain these types of numerically coded values that represent integers, real (floating point) numbers, truth values, and Unicode characters.

But we have already seen that more flexible data types do exist; at least we have seen strings of characters, and printed them out -- starting from the very first Hello World! application. Actually we are dealing with data structures that are compounded from the primitive types by using "data abstraction mechanisms" provided by the programming tool of choice. In the case of Java, the abstraction mechanism is object-orientation.

What is an object? Philosophically it is "a thing that you can think of". For example, philosophically 'the weather' is an object, you are an object, and also all your friends and their houses and bikes and home countries are objects. A shimmering, blue, bitter smelling but sweet jelly cake is an object... You can think of these things.

What properties does an object have? Important things to notice:

  • An object is an individual. Whatever you describe as an object, is exactly one thing that exists. You can say "my apartment" when you mean one particular place. You can say "student apartments all over Finland" when you mean one collection of places. You think about an object (the collection) that contains several other objects.
  • Objects have an "address". We can call this a reference. Think about your cell phone. (You can think about it, so it is an object...) Anybody who has another phone and your phone number, can call you. Usually you see the caller's number on your cell phone when it rings. Let us say that the phone number is a reference that can be used to communicate to your phone. Clearly a phone number is unique -- a reference to an object is, since the object is unique. But there can be many copies of the number, each referring to the same object.
  • Objects naturally are compounded of many objects. As the cell phone is attached to your ear and mouth, and ultimately to your mind, philosophically you are a network of connected objects -- a system which facilitates "Having a telephone conversation". The system itself can be considered an object, although it actually contains many smaller ones within itself. A telephone conversation cannot happen without the phone; you need a number of specific, interconnected objects in order to make systems function properly. The objects need to be of a proper type, and properly interconnected, in order to make something work. (For most purposes, you don't need an elephant to make a phone call, but to make a circus act, an elephant might be required.)
  • An object has to exist in order to do anything purposeful. If one doesn't exist, you need to create a new object, or ask help from a factory that will create it for you.
  • Objects can be classified, that is, of any object you can say which class it belongs to.
  • The class defines what attributes, properties and capabilities belong to an object that belongs to the class.

Some examples of classes in "real life":

  • Paavo, Chris and Kanako are persons.
  • Your seat in a lecture hall is clearly an instance of a Seat.
  • Classification is usually hierarchical: Object of type Seat is more generally an object of type Furniture.

What actually matters in classification is the interface of an object that belongs to a class. By interface, we simply mean the possible ways of interaction with an object. Each class of objects has its own interface. And it is less restricting to talk about interfaces rather than only classes because quite different classes can have the same interface. Think about my previous example where all tables and all seats and also desktop computers and even the head of a careful lecturer provided the interface that allows one to place a thing on top of the other object. It was immediately found out that this interface was not found in any of the wall objects.

In object oriented computing, using Java as an example:

  • an object is a model that represents any philosophical object that is interesting in an application. For example, a banking software might deal with users and bank accounts. Each user would be represented by an object of class User. A bank account would be represented by an object of class Account. Users and accounts would be interconnected, and there would be plenty of objects of other classes such as Transaction, InterestRate, BankOffice, ATM...
  • each object belongs to a class which needs to be defined.
  • each class implements a set of interfaces.

Creating and using objects: Qurzw

Objects of class Qurzw have the following interface: You can create a Qurzw that is of a certain color (pink by default). You can warm up the Qurzw, and you can query it's current temperature. It is not possible to cool down a Qurzw, and when it overheats it becomes black forever. This is what a Qurzw is like. I can think about such a thing, so it is apparently a class of objects. I can make a model for such a Qurzw in Java:

public class Qurzw{
    private String color;
    private double temperature;

    public Qurzw(){
        color = "Pink";
        setTemperature(21.0);
    }

    public Qurzw(String color){
        this.color = color;
        setTemperature(21.0);
    }

    public Qurzw(String color, double temperature){
        this.color = color;
        setTemperature(temperature);
    }

    public double getTemperature(){
        return temperature;
    }

    public String getColor(){
        return color;
    }

    private void setTemperature(double newTemp){
        temperature = newTemp;
        if (newTemp>100) color = "Black";
    }

    public void warmUp(){
        setTemperature(getTemperature()+1.0);
    }

    public void warmUp(double howMuch){
        setTemperature(getTemperature()+howMuch);
    }
}

This is what object oriented programming is about: It is modelling the world using classes as an abstraction mechanism. So... I have defined a model, a class of objects of type Qurzw, and placed the model into a Java compilation unit. Try to examine the class definition. Then, try to make a program that creates a couple of Qurzws, warms them up, and prints out their colors. It could be in a different compilation unit, like TestQurzws.java. Something like the following:

public class TestQurzws{
    public static void main(String[] args){
        Qurzw cuteQurzw = new Qurzw();
        Qurzw coolone = new Qurzw("Orange");
        Qurzw hot = new Qurzw("Magenta", 90);

        System.out.printf("Overall temperature of the qurzws is %g degrees%n",
                cuteQurzw.getTemperature()
                + coolone.getTemperature()
                + hot.getTemperature());


        System.out.println("What color is the qurzw: " + hot.getColor());
        hot.warmUp(20);
        System.out.println("What color is the qurzw now: " + hot.getColor());
    }
}

It will be very instructive to run this program, and some variations, using the step debugger! You'll see how the execution flow goes in and out of the methods of Qurzw, and how the internal state of each individual changes as the method calls are performed.

Creating and using objects: Strings

Eventually you'll have to be able to read the Java platform API documentation, so you could as well have a look into some of the documentations already:

The class java.lang.String is a very fundamental one because objects belonging to it represent character strings. Each string literal that you might write in your applications, like "Hello world!" in the first one, become objects of class String. When you use such a literal, you are using a reference to an object of class String.

Try out some operations that seem to be possible with the basic strings:

String hello = "Hello";
String world = "World";
String hw = hello;
hw += " ";             // The operator '+' for Strings is a small
                       // "quirk" in Java; maybe
                       // more about this later...
hw += world;

hw = hw + hello + "!";

System.out.println(hw);


// Try out some method calls for the object:

int slength = hw.length();
System.out.printf("Length of my string is %d%n", slength);

System.out.printf("The first character is %c and the last one %c%n",
        hw.charAt(0), hw.charAt(slength-1));

// Do you think this is possible:

char c = hw.charAt(slength);

Exercise 2: String

Then make a subroutine that iterates through a String object, and finds out how many times a certain character is present in the string. Usage would be like the following:

char ch = 'k';
String st = "Kan we think of trinking some koffee, Khaled?";
System.out.printf("My string has %d occurrences of the letter %c",
        countChars(st, ch));
// I expect my subroutine to return the integer 3 for the above case
// since 'k' and 'K' are different characters...

Exercise 3: StringBuilder

An object of the class String can never change form since it is created. We say it is an immutable class. It is a good thing that can be trusted. But when you need a mutable character string, for example, for changing one character to another character, you need to use the class java.lang.StringBuilder. Documentation is there: http://java.sun.com/javase/6/docs/api/java/lang/StringBuilder.html

Examples of use:

// A canonical way of creating any kind of object with the default
// state (which, for StringBuilder, is an empty character string):

StringBuilder myBuilder = new StringBuilder();

myBuilder.append("Hello");    // You can append a String

System.out.println(myBuilder.toString()); // You can convert to String.

myBuilder.append(' ');  // You can append a char

myBuilder.append(2);  // You can append an integer

System.out.println(myBuilder.toString());

myBuilder.append(" Worlds!");

String resultingText = myBuilder.toString(); // You can convert to String.

System.out.println(resultingText);

myBuilder.setCharAt(0, 'Y');
myBuilder.insert(5, 'w');

System.out.println("New one: " + myBuilder.toString());
System.out.println("Old one: " + resultingText);

myBuilder.delete(6, 8);

System.out.println("New one: " + myBuilder.toString());
System.out.println("Old one: " + resultingText);


// This is how you manipulate objects: you call public instance
// methods of the class, and you tell the method a reference to an
// object individual on which it should operate. There's no
// difference to the way of use, no matter what the object is.

Your assignment:

Make a subroutine that takes a StringBuilder reference as a parameter, and manipulates the string so that after return from the subroutine, occurences of a certain character have been replaced by another character. Of course, the subroutine takes as additional parameters the character that has to be replaced, and the character that will replace the other one. You need to iterate over all the characters using a loop structure, and handle the characters differently according to some condition. Have fun creating a replaceChars(stringb, oldChar, newChar) or the like!

Creating and using objects: arrays

A primitive type like an integer or a double precision floating point variable is useful, of course, but many times one value is just not enough. You need arrays of values instead. An array is an indexed set of values of a certain type.

Exercise 4: int[]

This is how you declare and create an array of integers in Java:

int[] myArr = {1,2,3,4,5};  // Arrays can be initialized with values.

int[] myOtherArr;           // But they don't have to be...

myOtherArr = myArr;         // Arrays are objects! Now we have two
                            // references to the same object individual!

// (print out values:)
System.out.println("One array:");
for (int value: myArr) System.out.printf("%d ", value);

System.out.printf("%nOther array:%n");
for (int value: myOtherArr) System.out.printf("%d ", value);

System.out.println();


myArr[2] = -7890;   // This is how you get to an indexed value


System.out.println("One array:");
for (int value: myArr) System.out.printf("%d ", value);

System.out.printf("%nOther array (or is it the same one??!):%n");
for (int value: myOtherArr) System.out.printf("%d ", value);
System.out.println();

myOtherArr = new int[6]; // This is how you can create a new
                         // array of some size, without initializing values
                         // IF I remember correctly, the Java machine
                         // guarantees initialization to zeros; but beware
                         // the programming language that you use; might
                         // as well be random contents!

System.out.println("One array:");
for (int value: myArr) System.out.printf("%d ", value);

System.out.printf("%nOther array (is it still the same?):%n");
for (int value: myOtherArr) System.out.printf("%d ", value);

System.out.println();

Your assignment:

Make a subroutine that returns a new integer array that is filled with a range of numbers from an endpoint to another. Usage could be like the following:

int[] range = makeIntRange(-3, 2);

// I want to see the numbers -3, -2, -1, 0, 1, 2 after the print:

for (int value: range) System.out.printf("%d ", value);

Exercise 5: double[]

The array elements can be of any type (i.e., any of the primitive types, or references to any kind of objects) as long as all the elements in the array are of the exact same type. So we continue with real numbers instead of integers... Make a subroutine that creates and returns a new array of double values. The values have to be equidistant points on the real axis. Example of use:

double[] points = makeDoubleRange(1.0, 2.0, 11);

// I want to see the 11 equidistant numbers from 1.0 to 2.0 from the
// following printout. I.e., 1.0, 1.1, 1.2, ... 1.9, 2.0

for (double value: points) System.out.println(value);

Exercise 6: Command line arguments as an array of String-type references

Recap: The array elements can be of any type. Now we are ready to understand what it means to write the String[] args in public static void main(String[] args).

Try out the following program:

public class PrintArgs{
    public static void main(String[] args){

        for(int i=0; i<args.length; i++){
            String jono = args[i];

            System.out.printf("Argument %d is: %s%n", i, jono);
            System.out.printf("It's length is %d chars.%n", jono.length());
            System.out.println("First char is " + jono.charAt(0));
            System.out.println("Last char is "
                  + jono.charAt(jono.length() - 1));
            System.out.println("In upper case letters it's " + jono.toUpperCase());
            System.out.println();
        }
    }
}

The code won't do much unless you run it from the command line, and give some additional arguments to the launch command. So try it in the Command Prompt like this:

javac PrintArgs.java
java PrintArgs  Hello, you "nice programme"

Try to figure out the program completely. Then try to produce a program that works as follows, from the command line. You'll need a couple of if-statements there to take the special cases into account:

javac ArgsParser.java

java ArgsParser
You have to give an argument!

java ArgsParser what parameter
You have to give exactly one argument!

java ArgsParser ok
Hello, ok!

java ArgsParser what
Hello, what!

java ArgsParser Nieminen
Hello, Nieminen!

java ArgsParser Paavo
How's the course progressing?

java ArgsParser fine.
Hello, fine.!