Showing posts with label constructors. Show all posts
Showing posts with label constructors. 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

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.