There's a saying that goes:

"Each head is a whole different world."

Which I find to be true. Some may argue that a certain teacher doesn't know how to do his/her job, but maybe it's that the way he/she teaches is not compatible with the way your brain is "wired". I guess this is one of those things that is not just right or wrong.

Many things are open to interpretation, which may lead to the loss of valuable information.

So, today I want to explain the way the idea of a class clicked for me. Not just in a conceptual way, but also on why they are useful in our code:

One of the first things we learn when we start programming are variablesand constants.

So, if we are given the task of printing on the console your nameage and height, you'll probably do something like this:

Note: I decided not to include using a class like Scanner to request input from the user to keep it as simple as possible.

// Java

public class Main {
    public static void main(String[] args) {
        String name = "Chris";
        int age = 23;
        double height = 1.85;
        System.out.println("name: " + name + ", age: " + age + ", height: " + height);
    }
}

Which would output:

name: Chris, age: 23, height: 1.85

Great!

But, now we want to make our variable names a little more descriptive, how about adding a "chris" prefix? Check it out:

// Java

public class Main {
    public static void main(String[] args) {
        String chrisName = "Chris";
        int chrisAge = 23;
        double chrisHeight = 1.85;
        System.out.println("chrisName: " + chrisName + ", chrisAge: " + age + ", chrisHeight: " + chrisHeight);
    }
}

Nice!

Now, let's add another person's info:

// Java

public class Main {
    public static void main(String[] args) {
        String chrisName = "Chris";
        int chrisAge = 23;
        double chrisHeight = 1.85;
        System.out.println("chrisName: " + chrisName + ", chrisAge: " + age + ", chrisHeight: " + chrisHeight);

        String danielName = "Daniel";
        int danielAge = 27;
        double danielHeight = 1.71;
        System.out.println("danielName: " + danielName + ", danielAge:" + danielAge + ", danielHeight:" + danielHeight)
    }
}

Hmmm... 

Are you starting to see a pattern?

We are storing the same 3 values from 2 different people...

This is when a class comes to the rescue!

Let's refactor our code step by step by focusing on one person at a time.

The Chris class

In OOP (Object Oriented Programming), classes are made to represent both state and behaviour with a high level of cohesion. In english: that means that the variables and methods of a given class are related to each other. If a method does not use any of the variables inside a class, it's probably a sign that it is where it doesn't belong.

Now that we have this idea, we can make a Chris class with a default constructor that will take the values of chrisNamechrisAge and chrisHeight:

constructor is a special kind of function that must have the same name as the class it belongs to + have no return value (doesn't even need the voidkeyword), which is normally used to make sure that an instance of that classis in a valid state.

Valid state means that an object has the values that are expected.

An object is a concrete implementation of a class (we will see it in action later).

So, our Chris class would look like this:

// Java

public class Chris {
    private String name;
    private int age;
    private double height;

    public Chris(String name, int age, double height) {
        this.name = name;
        this.age = age;
        this.height = height;
    }
}

The keyword this is used to refer to the global scope of our class in order to differentiate the name parameter of the constructor from the actual global scope's name.

Now we can refactor our code in order to use our new and shiny Chris class!

So, instead of:

String chrisName = "Chris";
int chrisAge = 23;
double chrisHeight = 1.85;

We can have:

Chris chris = new Chris("Chris", 23, 1.85);

The keyword new is used to refer to the constructor of our Chris class.

And chris (notice the lower case "c") is what we call an object, because it is a concrete or "real" implementation of our Chris class.

But since we don't have our chrisNamechrisAge and chrisHeightanymore, our code won't compile correctly.

Interesting...

How can we fix this?

Well, if we go back to our Chris class implementation, we can see that our global scope's variables (also known as fieldsprivate fields or member variables) are private. So, we can't access them from the outside.

In order to be able to do that, we must add public methods that can help us access that data.

// Java

public class Chris {
    private String name;
    private int age;
    private double height;

    public Chris(String name, int age, double height) {
        this.name = name;
        this.age = age;
        this.height = height;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public double getHeight() {
        return height;
    }
}

Did you notice how those get...() methods don't use the this keyword? That's because there are no parameters that can match their names, so the compiler knows that we are referring to the global scope's variables instead.

Now that we have these methods, we can access them by using the dot (.) operator, like this:

// Java

public class Main {
    public static void main(String[] args) {
        Chris chris = new Chris("Chris", 23, 1.85);
        System.out.println("chrisName: " + chris.getName() + ", chrisAge: " + chris.getAge() + ", chrisHeight: " + chris.getHeight());

        String danielName = "Daniel";
        int danielAge = 27;
        double danielHeight = 1.71;

        System.out.println("danielName: " + danielName + ", danielAge:" + danielAge + ", danielHeight:" + danielHeight)
    }
}

That's better!

No, wait...

Now we gotta do the same for Daniel, let's create a Daniel class:

The Daniel class

// Java

public class Daniel {
    private String name;
    private int age;
    private double height;

    public Daniel(String name, int age, double height) {
        this.name = name;
        this.age = age;
        this.height = height;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public double getHeight() {
        return height;
    }
}

And now our Main class would be:

// Java

public class Main {
    public static void main(String[] args) {
        Chris chris = new Chris("Chris", 23, 1.85);
        System.out.println("chrisName: " + chris.getName() + ", chrisAge: " + chris.getAge() + ", chrisHeight: " + chris.getHeight());

        Daniel daniel = new Daniel("Daniel", 27, 1.71);
        System.out.println("danielName: " + daniel.getName() + ", danielAge:" + daniel.getAge() + ", danielHeight:" + daniel.getHeight())
    }
}

Nice!

Now our Main class is shorter than before.

But there's still one more thing we need to do...

If you really think about it, we are basically doing the same logic inside our Chris and Daniel classes ????.

Which means we are not using the right abstraction for this particular case. In order to find a solution, we need to know what Chris and Daniel are...

That's right! They are both a Person.

So if we delete the Daniel class and rename our Chris class to "Person", our code would end up being:

// Java

public class Main {
    public static void main(String[] args) {
        Person chris = new Person("Chris", 23, 1.85);
        System.out.println("chrisName: " + chris.getName() + ", chrisAge: " + chris.getAge() + ", chrisHeight: " + chris.getHeight());

        Person daniel = new Person("Daniel", 27, 1.71);
        System.out.println("danielName: " + daniel.getName() + ", danielAge:" + daniel.getAge() + ", danielHeight:" + daniel.getHeight())
    }
}

What benefits did we get?

  • Our code is now shorter and without losing it's meaning.
  • We reduced the need of 2 new classes to 1.
  • We reduced the noise of repeating both "Chris" and "Daniel" in more places than needed.
  • We managed to reuse our logic in a single class.
  • Now we can quickly know that both chris and daniel are concrete implementations of the same class, or how I like to call them: brothers.
  • Now we can use this Person class even in other projects and it will still work just fine.

Final words

I hope this example can help you, Mr./Mrs. Reader, to clear out your thoughts on what class are and why we use them in Object Oriented Programming :)

Guest Blogger

emmawedekind profile

Special thanks to our guest blogger Christian Vasquez, a Software Engineer for his contribution to the Ronald James Blog this week.

twitter chrisvasqm github chrisvasqm

Who Are Ronald James?

We are a leading niche digital & tech recruitment specialist for the North East of England. We Specialise in the acquisition of high-performing technology talent across a variety of IT sectors including Digital & Technology Software Development.

Our ultimate goal is to make a positive impact on every client and candidate we serve - from the initial call and introduction, right up to the final delivery, we want our clients and candidates to feel they have had a beneficial and productive experience.

Contact our Team

If you’re looking to start your journey in sourcing talent or find your dream job, you’ll need a passionate, motivated team of experts to guide you. Check out our Jobs page for open vacancies. If interested, contact us or call 0191 620 0123 for a quick chat with our team.

Let's be Friends!

Follow us on our blog, FacebookLinkedInTwitter or Instagram to follow industry news, events, success stories and new blogs releases.

 

 

Back to Blog

</Follow Us>