Showing posts with label object orientation. Show all posts
Showing posts with label object orientation. Show all posts

Saturday, June 11, 2016

Basics: Just what IS an object, anyway?

This is a pretty long one by the standards of this blog.  Try to stay with it, though, the concepts are crucial.

Whether people are experienced developers used to procedural languages or newcomers to programming in general, really understanding objects tends to be a bit of a sticking point.  It's odd, because once you start to get it, everything seems quite natural.

An object is a representation of...  something.  Sometimes they represent fairly nebulous concepts, sometimes they represent very real physical things, but in all cases they're a kind of model.  Objects have properties, just like a flower has a color or a bee has [6] legs.  Objects have methods, which are really just things you can ask them to do, like 'release pollen' or 'sting someone'.  Finally, objects have events, or at least they can generate events.  That could be 'I've been pollinated' or 'I left my stinger in someone'.  Any particular object may make use of one, two or all three of these constructs.

Objects are based on classes in Java.  There is an all too human tendency to use the terms interchangeably and I've probably been guilty of doing that, too.  Technically, a class defines how an object should be built and an object is an instance of such a class.  Basically, after you write your code you compile it to create a .class file, and then when you run your code you can make a new object from said class. Making objects is easy enough, most of them get created (or instantiated) by using the new keyword like this:

    SimpleObject myObject = new SimpleObject();

Let's break that down:

First, we have declared that we're interested in working with a variable of type SimpleObject.  In other words, someone out there has written a SimpleObject.java file that defined a SimpleObject class and you're going to make an object from that definition.

That variable will be called 'myObject'.  We have to name our variables or we'd have a really hard time referring to them in our code!

We're not referring to a previously existing SimpleObject, we're going to make a completely new one.  The actual creation is handled by a constructor inside of SimpleObject.java, and we need to rely on that constructor doing its job, correctly setting up anything within the new object that needs to be in place.

Some objects don't appear to have constructors at all if you read the code, but that just means that there is no need for a constructor to do any setup work, so the programmer was able to rely on Java creating a default constructor for them.  The code for SimpleObject may have been written either way.  We don't care at this point, we just know we can call it.  I'll get back to constructors a little later when we talk about actually writing a class of your own.

Defining an class in Java is straightforward enough.  You don't really have to do any more than create a .java file with a bit of correct syntax.  The following example is enough to make a SimpleObject class (which really can't do anything but exist):

package com.oopuniversity.simpleobject;

public class SimpleObject {
}

Of course, a class that doesn't do anything isn't very useful, but I think it's good to have a picture in your head of all the 'extra' stuff that absolutely needs to be in place.  Code can look a bit busy to new developers, and its best to know what is basically template stuff that you should make sure is there and then ignore.

Just to break it down, that 'package' statement up at the top tells the compiler where the generated class file should go.  It's basically specifying an output directory, but using periods instead of slashes or backslashes.   Packaging is primarily an organizational tool and it turns out to be an important one later on.

Then we have 'public class SimpleObject' which tells us we're defining a class called SimpleObject.  That public keyword is important, it controls whether other objects in a larger program are able to create SimpleObjects or even refer to them at all.  For now, just use 'public'.  The day will come when you start to use other modifiers for specific reasons, but if you're reading this to learn you don't have those reasons yet.

Then we have some curly braces.  Those are ubiquitous in Java programs, and basically set boundaries for chunks of code.  In this case, they are setting the boundary for the beginning and end of the class, although they don't actually contain anything.  Anything between those brackets will be considered an attempt at having something be a part of SimpleObject.

Man, four paragraphs to describe three lines...  I guess a fair amount of information is consolidated down into even that useless bit of code!  Fortunately, that stuff always stays pretty much the same.  Once you understand that structure, you can kind of stop worrying about it and move on.

I mentioned above that I would talk about constructors.  Well, that time has come.  The following code is (aside from being in a different package) precisely identical to the previous code:

package com.oopuniversity.simpleobjectwithconstructor;

public class SimpleObject {
    public SimpleObject() {
    }
}

The only differences are:

  1. We changed the package definition, which lets us have this version of SimpleObject sit in the same project as the previous version without any conflicts.
  2. Now we have something new inside the braces that define the class.

The package definition is needed because I'm keeping everything inside one big project.  Just like you can't have two files with the same name in one directory, you can't have two classes with the same name in one package.

The new stuff inside the braces is defining a default constructor for SimpleObject.  It's public which means other objects can use it to make a new SimpleObject.  It has nothing between the parentheses, which means you can create a SimpleObject without having to give it any parameters, which are nothing more than pieces of information you give it (we'll talk about those soon).  Then it has some more of those fun curly braces, which again define boundaries.  Anything inside this particular pair of braces belongs not just to the class, but to the constructor itself.

Why would you want to write a constructor like this, making your class busier?  Well, you wouldn't, and that's why you get this for free with any class you write that doesn't bother defining a constructor of its own.  However, you DO need to know about and understand this for one simple reason:  It is also possible to define a class using a constructor (or a whole bunch of them if you like) that has parameters.  If you do this, the compiler will *not* create a default constructor for you and you won't be able to use a default constructor unless you explicitly write one.

https://github.com/OOPUniversity/OOP_Basics

Friday, June 3, 2016

Super basic object stuff

I am not going to rework this right now, I think it gets the main points across as is.

From a recent Reddit post:

What you are asking about is quite basic to object oriented programming. Let's start with the first point I'd like to make: PersonA and PersonB are exactly the same thing, except the data is different. However, they cannot be simple methods that return integer values, that will never fly. The values you're setting up are lost as soon as the methods end.
Instead, you want to create objects of type Person. You do this by creating a class called Person and setting up variables to represent the values you want. At its absolute most basic (and this isn't correct, it's just showing the idea) it would look like this:
public class Person {
    public int x;
    public int y;
    public int range;
}
This is more akin to what we used to call a struct in c. Ordinarily you'd have a lot more stuff in there, but adding that right now could inhibit understanding so I want to take this slowly.
With the above class you could do this in the class you've posted:
public static void main(String [] args) {
    Person a = new Person();
    a.x = 200;
    a.y = 100;
    a.range = 160;

    Person b = new Person();       
    b.x = 100;
    b.y = 400;
    b.range = 170;
After that, you could use 'a.x' or 'b.range' the same way you were originally trying to use 'xA' or 'rangeB'.
Remember when I said that I was just showing the basics? Well, objects are a lot more powerful than just bags of variables. Let's use just another couple of features.
First, let's make a 'constructor' for Person so you can slim down your code:
public class Person {
    ... //What you already have
    public Person(int newX, int newY, int newRange) {
        x = newX;
        y = newY;
        range = newRange;
    }
}
Now your main can do this:
Person a = new Person(200, 100, 160);
Isn't that nicer?
Next, let's add 'accessor' methods to Person. Accessors are also called 'getters' and there are good reasons to use them. Trust me on this, I'm on the train and don't have time to fully explain:
public class Person {
    ... //What you already have

    public int getX() {
        return x;
    }

    //Do the same thing for 'y' and 'range'
}
At this point, you could still do 'a.x = 5' or 'range = b.range'. We can prevent that by marking the variables as 'private'
public class Person {
    private int x;
    private int y;
    private int range;
    ... //what you otherwise already have
}
But wait! Now when I try to write a.x=5 I get some horrible error and everything is broken and the world is ending!
No, you just need 'setters', also known as modifiers to do the job for you:
public class Person {
    ... //Everything you already have
    public void setX(int newX) {
        x = newX;
    }
    // Follow the same pattern for y and range
}
Now the equivalent to 'int range = a.range' is 'int range = a.getRange()', and the equivalent of 'a.range = 50' is 'a.setRange(50)'.
There's a LOT more to OOP, we've really just scratched the surface. But just encapsulating your data in this way will go a long way towards making your programs more readable, maintainable and robust.
I have no doubt that questions are coming up in your mind. I tried to make this clear and left out a few niceties in the interest of getting it written quickly and not overloading you, but it's a lot to absorb. Please ask questions when you need clarification.

Wednesday, November 11, 2015

Stop giving me so much static

Let's talk about the keyword static for a moment.

There are two different uses for this in our code.  It can be applied to methods or it can be applied to variables.

When static is applied, it disassociates the item being declared from any specific instance of the class.  For methods, this means that the method can be called by anyone at any time without creating a new class of that type.  This can be particularly handy for utility functions, initializers, or any other chunk of code that wants to run without caring that it's about a particular person, bill, or list of stocks.  For variables, it mostly means that the value is shared across all instances of the class.

Static Methods

Static methods can be called without making a new class.  For instance, it could be used for a factory method, which is a design pattern that calls for objects to be built by calling a function to do so.

public class Person {
    ...
    public static Person createPerson(firstName, lastName) {
        ...
    }
}

You can call createPerson without having a Person object, like so:

Person.createPerson("John", "Doe");

Many utility functions are declared as static, and as a general rule they will need to operate free of any context supplied by objects.

Static Variables

Static variables come from the same basic idea of being disassociated from any specific instances of the class.  They're useful for maintaining overall context, for instance, if we want to keep track of how many Person objects we've created we could write something like this:

public class Person {
    ...
    private static int numberCreated = 0;
    ...
    public static Person createPerson(firstName, lastName) {
        ...
        numberCreated ++;
        ...
    }
}

Now, every time we invoke createPerson, we'll also be incrementing the value of numberCreated, and it will always be available as a statistic our programs can check.

Many times, inexperienced programmers will overuse static methods, because when they first start creating methods and functions, they just call them from main.  Your main method has to be static, and if you try calling non-static methods directly from it, the compiler complains.  So the path of least resistance is often seen as just making those other methods static too.  This does seem to work, but it goes against object oriented design principals, and it's best to nip this in the bud.  So they start with this:

public class OutputTest {
    ...
    private PrintStream outputStream = ...;
    ...
    public static void main(String [] args) {
        print("This is a test");
    }
    ...
    public void print(String message) {
        outputStream.println(message);
    }
}

But that fails because you can't call 'print' from a static context, so they change it to this

public class OutputTest {
    ...
    private PrintStream outputStream = ...;
    ...
    public static void main(String [] args) {
        print("This is a test");
    }
    ...
    public static void print(String message) {
        outputStream.println(message);
    }
}

That fails, too, because outputStream isn't static, so they change the code again:

public class OutputTest {
    ...
    private static PrintStream outputStream = ...;
    ...
    public static void main(String [] args) {
        print("This is a test");
    }
    ...
    public static void print(String message) {
        outputStream.println(message);
    }
}

And they're satisfied.  Everything works now!  I call this the static cascade, and I recommend avoiding it.  If you did not originally intend for these items to be shared and free of binding to specific objects, then don't go changing them to act that way.  

Get used to writing object oriented code.  Do this instead:

public class OutputTest {
    ...
    private PrintStream outputStream = ...;
    ...
    public static void main(String [] args) {
        OutputTest test = new OutputTest();  //The key!
        test.print("This is a test");
    }
    ...
    public void print(String message) {
        outputStream.println(message);
    }
}

While it might be a bit more of a conceptual leap, it's actually a far smaller change to the original code, and it opens your class up to being more adaptable to use in other systems.  It's also a necessary step towards object oriented thinking, so you might as well get it over with now.