Much of this blog series up to this point, and many other programming resources that you will find elsewhere on the internet, talk largely about implementation and syntax. I want to take a minute to talk about Object Oriented Programming Concepts.
For that reason this page will take a bit of different tone compared to the rest of this tutorial. Now that you are beginning to understand the “how” behind Java programming as you read through the series, I also invite to think about the “why.”
The Four Pillars
The “Four Pillars” of Object Oriented Programming will help you understand how to structure your code not just within Java, but within any Object Oriented Programming language, and arguably even further outside of that as well. Some savvy readers may notice that I have tried to pepper in explanations of these concepts earlier in the series, but we will recap them here.
Abstraction
Abstraction refers to the idea of hiding complexity and only showing what is necessary.
Back in our page on Functions I gave the example of reading a name in from a Scanner. We can abstract away the complexity of setting up our scanner, remembering to close our scanner to prevent memory leaks, such that the only thing that a caller to our method would need to know is the resulting name.
Abstraction can only be used to refer to the larger scale practice of trying to model real world objects through classes, functions, etc, such my oh so clever example of Ice Cream classes.
Encapsulation
Encapsulation refers to limiting the scope of different classes, attributes, and methods and providing controlled means to interact with them.
It is a very common practice for most or even all of the attributes within a class to have a private scope, and the attribute can only be accessed with getter and setter methods. Similarly, a class or method can have their scope limited if they are intended to only be used within that class or class hierarchy.
private String attribute;
public String getAttribute() {
return attribute;
}
public void setAttribute(String attributeParameter) {
attribute = attributeParameter;
}
Inheritance
We just talked about Inheritance in its own post but to briefly recap it here Inheritance allows us to create classes that can reuse attributes and methods from other classes. We can avoid duplicating common code by instead “inheriting” from some base class.
Polymorphism
Polymorphism is the idea that something can take different shapes in different circumstances.
One of the simplest examples of polymorphism is the ‘+’ operator.
System.out.println(2 + 2); //4
System.out.println("Code " + "To " + "Live " + "By"); // "Code To Live By"
“Adding” two integers together will give you the sum of those numbers. “Adding” two strings together will concatenate those strings together. The ‘+’ operator in this case is polymorphic, it performs differently based on its operands.
To give another example, “method overloading” allows us to define a method with the same name, but with different parameters.
public void doSomething(String parameter) {
// ...
}
public void doSomething(String parameter1, String parameter2) {
// ...
}
public void doSomething(int parameter) {
// ...
}
This is also an example of “polymorphism.” Our “doSomething” method can have different implementations based on the number and data types of parameters that are passed to it.
Don’t Repeat Yourself
In my opinion the principle of Don’t Repeat Yourself or DRY is one of the most important things to remember when you are coding.
Something that I see from less experienced programmers is “copy paste” programming where the same block of code will be copy-pasted over and over. Each block will do something slightly different, such as affecting a different variable or have a slight permutation in its logic.
It is almost always preferable to instead consolidate this logic into some sort of class or function. Then you will have an easier time expanding this to handle some small additional use case or calling it from additional places within the code. There is also a benefit in that if you should ever need to rewrite that code, that change only needs to be made in one place and all its occurrences will be updated, rather than having to also copy paste this change to each place it was originally copy pasted (and potentially missing some and causing enormous headaches that things aren’t functioning as expected.)