How I finally understood what a class is
Tags: beginners, oop, class, howifinallyunderstood
Published: 2018-03-05 02:32:12

---
title: How I finally understood what a class is
published: true
description: Everyone has their own way of interpreting things, this is how I did for the concept of classes.
tags: beginner, oop, class, howifinallyunderstood
cover_image: https://www.asiasentinel.com/wp-content/uploads/2015/12/Brandspeak-6-Idea-Economy-Closing-image.jpg
---

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 **variables** and **constants**.

So, if we are given the task of printing on the console your `name`, `age` 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
// 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
// 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
// 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!

![Superman on his way](https://media.giphy.com/media/a6b4OLwbXw4h2/giphy.gif)

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 `chrisName`, `chrisAge` and `chrisHeight`:

> _A `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 `void` keyword), which is normally used to make sure that an instance of that `class` is 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
// 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:

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

We can have:

```java
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 `chrisName`, `chrisAge` and `chrisHeight` anymore, 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 `fields`, `private 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
// 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
// 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
// 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
// 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
// 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 :)

See you in the next post!

# Bonus tip

This one comes from [@alphashuro](https://dev.to/alphashuro)'s comment down below: another benefit is that now we can replace the parts in our code where we print a `Person`'s information by making a function that takes a `Person` object, like this:

```java
// Java

public class Main {
    public static void main(String[] args) {
        Person chris = new Person("Chris", 23, 1.85);
        printPersonalInfo(chris);

        Person daniel = new Person("Daniel", 27, 1.71);
        printPersonalInfo(daniel);
    }

    public static void printPersonalInfo(Person person) {
        System.out.println("name: " + person.getName() + ", age:" + person.getAge() + ", height:" + person.getHeight());
    }
}
```

And by making this "small" change we get the benefit of not having to maintain two different lines of code. There's just only 1 place in our code that we have to change in case we need to present someone's information in a different way.

Thanks to Alpha for bringing this up.

Now, there's another adjustment that I would do to our code.

Since the `printPersonalInfo()` function is only accepting `Person` objects, this means this method is directly dependent of the `Person` class. Which means, it should actually be part of it!

So let's go ahead and move our function to the `Person` class instead of having it hanging around inside our `Main`:

```java
// Java

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

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

    // Imagine we still have the getters here :P
    // this is just to make the code block shorter.

    public void printInfo() {
        System.out.println("name: " + name + ", age:" + age + ", height:" + height);
    }
}
```

Now, you may have noticed that I had to make a few adjustments:

- Remove the `person` parameter.
- Replace each Getter methods calls for the global variables.
- Renamed the method from "printPersonalInfo()" to "printInfo()".

The last point can be optional or personal preference. Personally, I find the "Personal" part of the name to be little redundant since we know we will create a `Person` object later.

Ok, so now we also have to make some adjustments to our `Main` class with this new implementation:

```java
// Java

public class Main {
    public static void main(String[] args) {
        Person chris = new Person("Chris", 23, 1.85);
        chris.printInfo();

        Person daniel = new Person("Daniel", 27, 1.71);
        daniel.printInfo();
    }
}
```

If you think about it for a second, we don't even need the Getter methods, this way of doing things is related to one of OOP's principles known as "encapsulation" which is a topic for another post 😉.

🎊 Bonus points for you if you read the whole thing! 🎉