In this session, we will discuss:
We have already looked at how to create functions or methods and also how to create classes.You should refer to
A Simple Introduction To Java - Class and Method
Michael Otu ・ Mar 18 '22
Shape Class
The purpose of creating the Shape
class is to demonstrate the use of the this
keyword in java. The this
keyword refers to the instance of the class and we can use it with the .
operator to access the properties/fields and methods of the class anywhere in the said class.
Create a class,
Shape
.
Let the Shape
class have the following attributes and methods:
- length:
double
- breadth:
double
- area():
double
- perimeter():
double
The methods have the
()
The above ADT tells us that the class has two fields and two methods, the types and return types. It doesn't tell us how the methods are implemented. Try an implement the Shape
class.
public class Shape {
double length;
double breadth;
public Shape(double length, double breadth) {
length = length;
breadth = breadth;
}
public double area() {
return length * breadth;
}
public double perimeter() {
return 2 * (length + breadth);
}
}
What do you notice when you execute the Shape class?
// Main.java
public class Main {
public static void main(String[] args) {
Shape s = new Shape(2.5, 2.6);
System.out.println("Area: " + s.area());
System.out.println("Perimeter: " + s.perimeter());
}
}
It will appear that the output will become:
Area: 0.0
Perimeter: 0.0
But why the 0.0
s? This was because of our constructor. If you remember so far all our constructors have different names compared to the fields.
Replace the constructor with the snippet below:
public Shape(double l, double b) {
length = l;
breadth = b;
}
Now the output looks more correct and as expected just like the result below.
Area: 6.5
Perimeter: 10.2
Using different variable names was another way to solve the previous issue we had where all the outputs were 0.0
. We could have used the this
keyword.
Change the constructor to the snippet below:
public Shape(double length, double breadth) {
this.length = length;
this.breadth = breadth;
}
The output will be the same as the above. Using the same parameter names as the field names make our code, to some degree, self-documenting. What would l
and b
mean anyway?
We can use the this
keyword on the rest of the fields called in the area
and parameter
methods too. We should add void methods to print the area and perimeter with some text, informing the user or displaying the length and breadth of the shape. Let's call this method print
.
Our new Shape
ADT will be:
- length:
double
- breadth:
double
- area():
double
- perimeter():
double
- print():
void
Now our new class will look like the snippet below:
public class Shape {
double length;
double breadth;
public Shape(double length, double breadth) {
this.length = length;
this.breadth = breadth;
}
public double area() {
return this.length * this.breadth;
}
public double perimeter() {
return 2 * (this.length + this.breadth);
}
public void print() {
System.out.println("The shape has a length and a breadth of, "
+ this.length + " and " + this.breadth + ".");
System.out.println("Shape has an Area of " + this.area()
+ " squared units.");
System.out.println("Shape has a Perimeter of " + this.perimeter()
+ " units.");
}
}
Our little output will be:
The shape has a length and a breadth of, 2.5 and 2.6.
Shape has an Area of 6.5 squared units.
Shape has a Perimeter of 10.2 units.
Encapsulation
In java, there are four main concepts that we have to understand about Object-Oriented-Programming. These are Encapsulation, Inheritance, Polymorphism and Abstraction.
We'd discuss Encapsulation here and discuss the other three in a separate article.
So, what is Encapsulation? Do you remember what we discussed about access modifiers? We said access modifiers regulate access to class methods and variables. There are public
, protected
, private
and default
. The private
access modifier restricts the access to methods or variables declared as private
outside the class. The concept of Encapsulation revolves around the private
access modifier and how to resolve the problems that arise when the private
access modifier is used.
We can prevent the user of our class from directly accessing and modifying the state of the objects they create. This is done to hide implementation details from the user. We provide the user of our class with some public
methods to access the variables and or methods that we have declared private
.
If we consider the Shape
class, the length
and breadth
have no access modifiers. Well, they do, it's just that we didn't specify it. So it is by "default", default
. What this means is that the fields can be accessed by another class in the same package as the Shape
class.
Getters and Setters
I mentioned earlier that, we can hide implementation details by declaring some fields or methods private
than allowing indirect access to these fields and methods via some public
methods. These methods are known as getters
and setters
.
Let's experiment. Make the fields
in the Shape
class private
and in the Main
class, comment out s.print();
and do, System.out.println(s.length);
. What happened?
Well, on my side, I am using vscode and before I even completed the whole print statement a red squiggly line appear below the print statement. Saying, The field Shape.length is not visible. In vscode, neither length
nor breadth
showed up on the IntelliSense.
Now we know that when we make a field private
the field
will be inaccessible outside the class.
Now let's talk about getters
and setters
, what they are and how to use them.
We made the length
and breadth
fields private
which means we can not access them nor write them. We can not read their value nor can we reassign or update their value. With a public
getter method, we can return the said private
field. So if the return type of length
is int
, the getter will return an int
value which is the private
field. A setter is a public
method with no return type. Its return type is void. We use a setter to set a value for a private
field. Something like assigning a private
field a new value via some method. So the setter method will take the value as an argument and reassign the private
field with the passed argument.
The getter method looks like the snippet below:
public [type] getPrivateField() {
return this.privateField;
}
[type]
is just the data type. The getter method name starts with get
(which indicates that it is a getter method). The remaining part is mostly the name of the private field.
The goes for the setter method but in place of "get" we use "set".
The setter method looks like the snippet below:
public void setPrivateField([type] someValue) {
this.privateField = someValue;
}
Know that the type of someValue
and the said private
field must have the same type.
With this new information, update the Shape
class using getters
and setter
.
This is what my Shape
class now looks like after the new changes:
public class Shape {
private double length;
private double breadth;
public Shape(double length, double breadth) {
this.length = length;
this.breadth = breadth;
}
public double getBreadth() {
return breadth;
}
public void setBreadth(double breadth) {
this.breadth = breadth;
}
public double getLength() {
return length;
}
public void setLength(double length) {
this.length = length;
}
public double area() {
return this.length * this.breadth;
}
public double perimeter() {
return 2 * (this.length + this.breadth);
}
public void print() {
System.out.println("The shape has a length and a breadth of, "
+ this.length + " and " + this.breadth + ".");
System.out.println("Shape has an Area of " + this.area()
+ " squared units.");
System.out.println("Shape has a Perimeter of " + this.perimeter()
+ " units.");
}
}
Now in the Main
class, instead of System.out.println(s.length);
we can now do, System.out.println(s.getLength());
.
What do you think about getters
and setters
? Well, what I noticed is that, if I don't need direct access to the fields, I don't need getters
and setters
. In the Main
class, if we have nothing to do with the fields then we don't need getters
and setters
. Apart from setting the fields using the constructors, there hasn't been anywhere the fields were set so we can do away with the setters
. Know when to use the getters
and setters
. The basic knowledge here is restricting access.
Have a look at the print
method in the Shape
class.
public void print() {
System.out.println("The shape has a length and a breadth of, "
+ this.length + " and " + this.breadth + ".");
System.out.println("Shape has an Area of " + this.area()
+ " squared units.");
System.out.println("Shape has a Perimeter of " + this.perimeter()
+ " units.");
}
We can comment out the print
method and put its body in the Main
class where we placed System.out.println(s.getLength());
. We would have to change this
to s
and then use the getters
in place of the fields. Mine Main
class now looks like this:
public class Main {
public static void main(String[] args) {
Shape s = new Shape(2.5, 2.6);
// s.print();
System.out.println("The shape has a length and a breadth of, "
+ s.getLength() + " and " + s.getBreadth() + ".");
System.out.println("Shape has an Area of " + s.area()
+ " squared units.");
System.out.println("Shape has a Perimeter of " + s.perimeter()
+ " units.");
}
}
And the output I got was,
The shape has a length and a breadth of, 2.5 and 2.6.
Shape has an Area of 6.5 squared units.
Shape has a Perimeter of 10.2 units.
Note that it is advised to let a class do one thing. This was why I said we should come out of the print method. Even though we create the getters
and setter
for external use, we can also use them internally.
In the constructor, instead of assigning a private
field a value by assignment, use the setter. In the perimeter
and area
methods, use the getters.
Package
You may have heard of the term, Package at least once in your life as a human. I mean, as a java programmer you'd be dealing with packages a lot. So take what you know and translate that thought to java.
Do you know java has a Math
class? What about we create our own Math
class without the names of the classes conflicting. How do we do that? We use a package
. A package is just a folder. For our case as starters, the package just sits right in our root directory. There are some benefits to using packages
which include:
- we can group related classes which will make it easier to debug and maintain the codebase.
- this prevents the pollution of namespaces, no name will class with another.
- by default, packages restrict the access of class to outsiders but are open to the classes in the said
package
.
Create MyMath Package
To create a package all we have to do is create a folder and then create our classes in that folder.
Let's create a folder,
MyMath
in the root of project files. Now insideMyMath
folder, create a java class,Math
Now at the very top before the class header, put package MyMath;
. This indicates that Math
class is a file in the MyMath
package
.
My Math
class looks like this:
package MyMath;
public class Math {
}
Let's add two methods, addOne(int num): int
and incBy(int num, int val): int
. So as the method name suggests about their implementation, the addOne
method takes an int
argument and adds one to it then returns the result. incBy
takes two arguments, num
and val
. It adds val
to num
and returns the result. Since all the methods in the Math
class static
methods, let's make ours also static
.
package MyMath;
public class Math {
public static int addOne(int num) {
return num + 1;
}
public static int incBy(int num, int val) {
return num + val;
}
}
In the Main
class, let's clear the main
method's body. Now to use the new package we have created, we have to import it in the Main
class as import MyMath.Math;
So our Main
class will now look like this:
import MyMath.Math;
public class Main {
public static void main(String[] args) {
System.out.println(Math.addOne(1));
System.out.println(Math.incBy(1, 3));
}
}
There is a problem here. We can use our Math
class freely now but what about the java Math
class? Of course, we can use the java Math
class anywhere but we can not do that in our Math
class. It is for reasons like that we use packages.
I used the pascal case for my package name, the recommended approach is to have a root folder, then in the root folder, you'd have your package folder then your classes. so you'd import it as import root.package.ClassName;
. Note the use of the lower case for the root and package names. This is similar to import java.util.Scanner;
.
Conclusion
- OOP is a programming paradigm where classes are used to model real-life objects.
- There are four main concepts of OOP: Encapsulation, Inheritance, Polymorphism and Abstraction.
- Encapsulation means data hiding, making use of the
private
keyword which restricts access to fields or and methods declared asprivate
. - We make use of getters and setters to make
private
fields or and methods available to classes outside the said class. - We can use packages to group related classes and this prevents namespace pollution.
Projects
The projects here will be simple (not easier). We would implement the back account program using the knowledge we've acquired so far.
- A bank account has an account name, account number and pin.
- One can deposit and redraw from one's bank account.
- One can check their balance.
- After a withdrawal or a deposit, display a message saying how much the account owner previously had before the transaction was made, the amount used in the transaction and what their new balance is.
- We can not have a balance less than zero and we can not deposit nor withdraw a negative amount from the balance.
- Make the program interactive by asking the user to input their account name, number and pin when the program is first executed.
- Assign the user an initial balance of 100.
- Provide an interactive means for the user to deposit, withdraw or exit the program.
TIPS: Have a different class for the bank account and another for the interactivity (the main class will also do). Use integers for the amounts. If you think you can add some functionality that is not mentioned, do so.
Source
- Sololearn
- DS Malik