Showing posts with label interface. Show all posts
Showing posts with label interface. Show all posts

Monday, December 15, 2014

Inheritance Part 2: That's Rather Abstract, Isn't it?

I hope you've been browsing through Java source code outside of your own and the small samples I've provided on this site.  Reading and trying to understand code can only help you in the long run.  You will encounter different code styles, you will see interesting data structures, API calls you didn't know existed, all sorts of stuff.

Today I'm going to talk about something you might have seen, but if you haven't, it's no big deal.  It is the keyword abstract.

We use abstract as part of the definition of a class, which indicates that while it is in fact a valid class file, nobody is allowed to create an object of that type.  That doesn't mean that it's useless though.  Remember, we have inheritance on our side.  You can create concrete classes (concrete is just the opposite of abstract, indicating a class from which you can create objects.  No special keyword is needed for that) that extend abstract classes all you want.

We also use abstract as part of method signatures when we want to create the idea of a particular method call but wish to defer the actual implementation of said method to our concrete classes.  This is similar in concept to interfaces, and sometimes it's more of a personal decision as to which you will use.

You see a lot of abstract classes in use when you look through frameworks, which are basically bodies of code designed to accomplish some function but with the details left up to the final developer.  There are business frameworks, logging frameworks, GUI frameworks, reporting frameworks, the list is very long.  Usually the trigger for creating a framework is when someone realizes they've just written the same thing for the fifth or tenth time, and that the differences between the various programs are relatively minor.  Maybe you query a database, format a report and write it to a file, and it's always the same except for the details of which fields you look for and print.

This is a great application for abstract classes.  Let's take a look at a simple one:

public abstract class Report {
}

Well, that's about as simple as it gets.  To be fair it's also about as useless as it gets but never fear, we'll fill in some details later.  Actually it's not entirely useless.  You might want to have a set of classes that all share a common base class so that you can collect them into a Collection of some sort, although you could also make this work with an interface.  Abstract classes really come into their own when you include some code within them.  So let's write something.

public abstract class Report {
    public abstract void GenerateOutputLine(String dataLine);
    public abstract String ReadData();

    public void runReport() {

        String dataLine = null;
        while( null != ( dataLine = ReadData() ) ) {
            GenerateOutputLine(dataLine);
        }
    }
    
}

OK, that was simple enough.  We have defined not only our abstract Report class, but made it do a little bit of work for us.  It calls ReadData until that method returns a null, and then takes the value returned from ReadData and passes it to GenerateOutputLine.  Of course, you can't actually run this report, you need to create at least one concrete class based on it.  That could be a simple test driver designed to make absolutely certain that your framework behaves properly with known data.  It could be something that reads from one file and writes to another, which would basically give you a 'copy file' command.  It could be something that reads one file, does some calculations or modifications, and then spits out the changed data.  The options are nearly endless, despite the fact that this is a highly simplified example.

Let's write a simple test driver:

public class ReportTester extends Report {

    public static void main(String[] args) {
        ReportTester rt = new ReportTester();
        rt.runReport();
    }

    String [] dataLines = {
        "one", "two", "three", "four", "five"
    };
    int lineNumber = 0;

    public void GenerateOutputLine(String dataLine) {
        System.out.println(dataLine);
    }

    public String ReadData() {
        String toReturn = null;
        if (lineNumber < dataLines.length) {
            toReturn = dataLines[ lineNumber++ ] ;
        }
        return toReturn;
    } 
}

Now if we were to run 'ReportTester' we'd get the output:

one
two
three
four
five

The main driver of the program is still in that 'Report' superclass, but the implementation details have been kept in ReportTester.  We run the code in Report, and it calls the methods it finds in ReportTester to do the work.  ReportTester itself is quite simple.  In addition to a simple main that does nothing more that create ReportTester and run it (actually running that method from the superclass Report), it defines the specific implementations for our two abstract methods.  One method does nothing more than write to the console and I hope I don't need to explain that.  The other goes through an array of Strings, returning the next one in the array and increasing the index value each time it's invoked until it reaches the end of the list, at which time it returns a null which triggers the end of the loop in 'runReport'.

This is of course tremendous overkill for a program of this size, but as your projects get more involved, the ratio of abstract code to concrete code is likely to change quite a bit.  System maintenance gets easier and faster, and your software gets more robust.  After all, a bug fix to a framework may take care of issues across several dozen different specific implementations of different reports.

I will of course revisit this topic later, because we've only scratched the surface of the possibilities brought on by object orientation.  With enough small components intelligently built, one can assemble new programs almost like putting together Tinker Toys or Lego.  One's systems can be defined in large part by configuration files, and changed easily at will, all without writing, testing or deploying new code.


Monday, November 24, 2014

Collections Part 2: Map

It's time to talk about the Map.

Sometimes we need to store and retrieve information based on its relationship to other information in a keyed fashion.  There are a lot of reasons for this, but for the purpose of this post we'll pretend that we want to store product descriptions based on item numbers.

So I have a store, where I sell an eclectic group of items:

Item #Item Name
100001Tooth straightener
100002Dust Collection
100101Pickled Snail Shell
100201Odor Vent
200001Checkerboard Paint
200101Toenail Fastener

Oddly, business has not been very good lately.

 Now, if I wanted to computerize my system, I might decide that I wanted a way to have the system display the description of an item when the item number was entered (or selected from a list, or something).

 Let me start by saying it would be entirely possible to create two parallel arrays of String variables, such that itemNumbers[0] contains "100001" and itemNames[0] contains "Tooth straightener".  One could search through the first array for the item number for which you were looking, take the index value you found and display the value from the second array.  This can get a bit clumsy, and it would take a lot of work to keep everything in sync, but it could work just fine (albeit a bit slowly when the number of items gets large).  Adding items would be relatively easy.  Deleting them would be annoying, because you'd have to move all the items down.  There are other ways you could do it, too.

But doesn't the following seem quite natural and easy?

    //Get name of item based on item number
    String itemName = products.get(itemNumber);

    //Add new item type to product list
    products.put(newItemNumber, newItemName);

    //Remove obsolete item type from product list
    products.remove(oldItemNumber);

Enter the Map.

A Map is a Collections framework interface designed for just this purpose.  Keyed lookups like this are very handy, and the Map makes it easy to set up, too.

Like List, Map is just an interface.  You will need to create an actual object that implements the Map interface in order to use one, and the most likely candidate is the HashMap.

So your code would look like this:

In the old days, before generics:

    Map products = new HashMap();

Or if you're working in this century:

    Map<String, String> products = new HashMap<String, String>();

The two object types are the key and the value data types, respectively.


Friday, November 21, 2014

Collections Part 1: List

Let's talk about Collections.  I don't mean baseball cards...  or dust.  I'm talking about the Collections framework, which is a powerful set of classes included with your Java distribution.

This is not meant to be an in depth tutorial.  I'm merely going to scratch the surface and give a few guidelines regarding basic use of the framework.

The Collections framework is incredibly important to the Java developer.  You will spend a great deal of time working with the data structures within it.  The two that you will most likely use more than any other are List and Map.

List and Map are not classes.  They are interfaces.  An interface can be thought of as the set of controls for a range of classes.  Much like you might have a gas powered or electric powered oven, you still turn a dial and set a desired temperature.  The interface is the same, although the implementation is different.  This is a key concept:  Code to the Interface is commonly said, and slightly less commonly actually done.  I will do other posts on this idea, it's very important.

Let's start with List.  We'll do Map in another post.

Suppose I wanted to keep track of a few numbers read in from a file.  Each line contains one number, but I don't know how big the file is.  While it would be possible to load the numbers into an array, it would be a bit messy, as I would have to manage the size of the array.  Enter the 'ArrayList'.  This is a Collections based object that works very much like an Array with a turbocharger on it.  I don't have any hard numbers on this, but my suspicion is that it is the most commonly used Collections class out there.

Let's say my pseudocode looks something like this:

Open a file

For each line in the file:

    Read an integer number from the file
    Store the integer in a list for later use

Generate a sum of all the integers in the list as SumTotal
Display SUM to the user

There are multiple paths to success of course, and it's hard to say that any given solution is exactly 'wrong'.  However, unless we know in advance how many values we're going to store, or we wildly oversize the initial allocation, using an array would require us to modify the length of the array regularly.  It's not that this is particularly hard, but it's even easier not to do it.

And let's face it:  One of the secrets of successful programming is doing things the easy way.  It's a hard enough job, there's no reason to add unnecessary bells, whistles and epicycles to our code.

I'm not going to address the bits about reading the file right now, that will be in another post.  I just want to concentrate on 'Store the integer in a list for later use' and 'Generate a sum of all the integers in the list as SumTotal'.

First, we have to create the ArrayList object.  I'm going to do so in a way I haven't shown you before, but it's not too awful to understand:

List<Integer> numberList = new ArrayList<Integer>();

What?

Well, honestly Java can deal with this without having those '<Integer>' parts, but I thought you ought to get used to using them.  They're really handy for preventing certain classes of errors when programs get bigger.

What this is doing is creating a variable called 'numberList'.  It is an object of type 'List', and that 'List' is constrained to hold only Integer values.  That's the reason for the syntax, it makes sure we don't do something silly like try to put a String or a PersonData in there.

List is NOT a class.  You cannot create a 'new List()' directly.  It is what's known as an interface, and essentially describes how to use a category of classes, rather than one single class.

ArrayList IS a class.  You could do this if you so choose:

ArrayList<Integer> sillyNumberList = new ArrayList<Integer>();

This is roughly akin to adding the name of the manufacturer before mentioning an appliance.  Every time.  You wouldn't tell someone to go get you a beer from the Acme refrigerator, you'd just say refrigerator.  The fact that it's an Acme was only important when you bought it (or when you need to have it repaired.  Don't ask me about refrigerator repair, it's a sore spot).  The fact that it's a refrigerator means that you will grab a handle, pull it, and find something yummy and cold inside.  The specific manufacturer does not matter.  Similarly, a List allows you to add items, remove items, look at items and such, all without having to know that it is specifically an ArrayList.

Let's imagine that we've now got a value we want to add as an Integer, in a variable called 'numberToAddToList' (imaginative, huh?)  We'd just do this:

numberList.add(numberToAddToList);

No muss, no fuss, no checking capacity.  Set it and forget it.  You can do this once, or a thousand times or more.  That one line is all you'll need to use.

The other bit we need to work on is generating a sum of the numbers.  The way to do this, of course, is to take all the numbers, one by one, and add them to a variable that started at zero.  I'm going to do this three times here.  The first time using a for loop the way we've already done.  Next, I'll do so using an 'Iterator', which is a helper type designed to go through all the items in a Collection one by one, has been around forever, and is oftentimes a better choice than a standard for loop.  The last is using the 'enhanced' for loops that have been in the Java spec for a few years now.  None of these ways are strictly wrong, but if I was reviewing your code I'd want to see or hear a good reason for not doing it the third way.

Integer sumTotal = 0;

1)
for (int i = 0; i < numberList.size(); i++ ) {
    sumTotal = sumTotal = numberlist.get(i);
}

2)
Iterator<Integer> iter = numberList.iterator();
while(iter.hasNext()) {
    sumTotal = sumTotal + iter.next();
}

3)
for(Integer number : numberList) {
    sumTotal = sumTotal + number;
}


In all cases, we'd just then write:

System.out.println("The total is " + sumTotal);

As I think you can see, the new enhanced for loop makes life pretty easy.  You declare a variable and state where it comes from, and then just use it in the loop.

The iterator probably looks pretty awful to you, and to be fair, that's the cleaned up version available to us since we got to start using Generics.  Back before we could add that <Integer> tag it would have looked like this:
Iterator iter = numberList.Iterator();
while(iter.hasNext()) {
    sumTotal = sumTotal + (Integer)(iter.next());
}

But it was still a useful construct quite often.  Naturally in small examples like these the full impact does not show itself.

List can be used for much more than numbers of course.  Any sort of Object can be stored in a list.  You can have a List of Strings, or a List of Lists, or a List of Maps...

Next time, we'll discuss Maps, which instead of sequential access specialize in looking up specific objects based on a key value.