Wednesday, November 19, 2014

Don't Treat me Like an Object

I originally posted this on Reddit, and got some positive feedback on it, so I thought I would put it up here as an early lesson in object orientation.  That is, after all, our goal here and a dozen posts in I haven't really mentioned it at all yet.

Moving from procedural code to object oriented code is a major leap and takes a real adjustment in thinking.
Very often, multiple pieces of data logically belong together. For instance, a person's given name and family name should generally not be separated. There's little point in having separate references to "John" and "Doe", after all.
This concept existed before object oriented programming did, in the form of 'structures'. In c we'd do this
struct PersonData {
    char givenName[20];
    char surname[20];
}
Which helped some. Now we could declare a variable of type PersonData and pass it around, knowing that the fields would be kept together. Believe it or not that was a big step forward.  Of course a bit of energy was spent on doing things like determining if '20' was enough storage for a name.  
Objects are basically structs with functions added, and with the ability to hide internal details from users of said objects.
So while it would be possible to recreate the above struct as an object like this:
public class PersonData {
    public String givenName;
    public String surName;
}
That doesn't really take advantage of the power of the language yet. Sure, we can now go:
PersonData johnDoe = new PersonData(); //Use default constructor that comes free
johnDoe.givenName = "John";
johnDoe.surName  = "Doe";
But we can do better. For instance, a person ALWAYS has those names, right?  So why allow a PersonData object to even be created without them? Enter the 'Constructor'. It's just a method designed for one purpose: To initialize a new object. We could insert the following into our PersonData class:
public PersonData(String given, String sur) {
    givenName = given;
    surName = sur;
}
And now we could write the earlier code like this:
PersonData johnDoe = new PersonData("John", "Doe");
This PersonData is quite limited as it stands right now, since it's got no methods on it. But you know, that's OK, there's a place for objects that just store data, too. It is, however, a starting point to think about how objects work.
Of course, a constructor can do much more than set values for a few fields, too, performing any sorts of setup and initialization that might be required.
Please note, I am not saying that exposing those variables as public is a good idea, and I would not write them quite that way for a production application, but I'm trying to keep this example simple to understand.

Since whenever you write Java code you're forced to put it into classes anyway, I suggest that you always treat your classes as though they're going to be objects.  Make your main() methods as minimal as possible.  In short,don't do this:

public class InputData {
    public static void main(String args[]) {
        Scanner s = new Scanner(System.in);
        while(s.hasNextLine()) {
        ...

Instead, write it like this from the start:

public class InputData {
    public static void main(String args[]) {
        InputData inputData = new InputData();
        inputData.execute();
    }

    public void inputData() {
        Scanner s = new Scanner(System.in);
        while (s.hasNextLine()) {
        ...

Note that by adding just a few lines I've turned this into slightly more object oriented code.  I've avoided the static cascade problem.  I've also made it so that if I want to I can use this object from some other piece of code without a great deal of trouble.  That code I have in main could be duplicated anywhere.

Tuesday, November 18, 2014

Arrays: A new dimension

Let's revisit arrays and take them quite literally to the next level.

To recap:  An array is a means for storing multiple values of the same kind.  Those kinds can be ints.  Those kinds can be Strings.  Those kinds can be...  other arrays.

The simplest way to think of this is to picture a grid.

int [] [] twoDArray = new int [3][3];

Would generate something akin to this:

012
0
1
2

Each of the empty boxes can hold an int value.

The type of twoDArray[0] is 'int []'.

To process ALL of the cells in this block you'd most likely write a nested set of for loops:

for (int i = 0; i < 3; i ++) {
    for (int j = 0; j < 3; j++ ) {
        System.out.println(i + ", " + j + ": " + twoDArray [i] [j] );
    }
}

Now the grid analogy breaks down just a bit when you make an array more complicated.  For instance, each row could have a different number of columns.  If you were building a more sophisticated application you would probably not want to hard-code the size of the arrays in your loops, but would be more likely to use:

for (int i = 0; i < twoDArray.length; i++) {
    for (int j = 0; j < twoDArray[i].length; j++) {

But the principle is the same.  

By way of example, let's make a table of five rows, where each row has one more column than the last.  We'll populate each cell with the product of the row and column indexes:

int [] [] twoDArray = new int [5][];

for (int i = 0; i < 5; i ++) {
twoDArray [i] = new int[i+1]; //NOTE THIS!  For each row we create a new row of boxes of the correct length.
for (int j = 0; j <= i; j++) {
twoDArray [i] [j] = i*j;
}
}

01234
00
101
2024
30369
40481216

To print out the contents one could simply write this:

for (int i = 0; i < twoDArray.length ; i ++) {
for (int j = 0; j < twoDArray [i].length ; j++) {
System.out.println(i + ", " + j + ": " + twoDArray [i] [j] );
}
}

Which would generate the following output:

0, 0: 0
1, 0: 0
1, 1: 1
2, 0: 0
2, 1: 2
2, 2: 4
3, 0: 0
3, 1: 3
3, 2: 6
3, 3: 9
4, 0: 0
4, 1: 4
4, 2: 8
4, 3: 12
4, 4: 16

It would certainly possible to put this into a more readable format if one wished, of course.

For instance, if you changed the code to this:

for (int i = 0; i < twoDArray.length ; i ++) {
for (int j = 0; j < twoDArray [i].length ; j++) {
System.out.print( twoDArray [i] [j] );
if (j < (twoDArray [i].length - 1)) {
System.out.print(",");
}
else {
System.out.println();
}
}
}

We've introduced something I haven't used before on this blog.  While System.out.println should be familiar, we also have System.out.print.  It's basically the same thing, but it doesn't end by creating a new line.  This gives us the option to add more text after it.  System.out.println() with no arguments just ends the current line of output.

The output from the above would therefore take the following form:

0
0,1
0,2,4
0,3,6,9
0,4,8,12,16

Which closely matches the table up above.  Naturally, if the arrays had been created in a more complex manner the output would reflect that.

This concept can be extended to three, four, or 12 dimensions if you so choose.  Mind you, it gets mighty hard to visualize past three,  Just remember that the content of an array cell can be pretty much anything, including another array.