Hi! In today's lesson, we'll get acquainted with the concept of access modifiers and consider examples of how to work with them.
Of course, saying 'get acquainted' isn't quite right: you are already familiar with most of them from previous lessons. Just in case, let's refresh our memory of the most important point.
Modifiers access are most often keywords that regulate access to different parts of your code. Why 'most often'? Because one of them is set by default without the use of a keyword :)
Java has four access modifiers. We list them in order from most restrictive to most 'lenient':
We considered it in a previous lesson. We made a serious mistake here: We make our data public, which allowed fellow programmers to access the fields directly and change their values. What's more... these values were assigned without any checks. This means that our program could create a cat named "" with an age of -1000 years and weight of 0. To solve this problem, we used getters and setters, and also used the private modifier to limit access to the data.
Basically, limiting access to fields and implementing getters and setters are the most common examples of how
However, as you'll remember from the lesson about interfaces, the user only gets access to the external interface. And our 4 methods are not part of it. They are helper methods: we created them to improve the readability of the code and to not cram four different tasks into one method. You don't need to give the user access to these methods. If users have access to the
the
But it would be easy for the data in the database to be in one format and we need it in another. Imagine that users' birthdates in the database is stored as <TIMESTAMP WITH TIME ZONE>...
...and instead we need the simplest object — a
And here's the basic reasoning: why would anyone outside a package need to see a helper class that only works with the classes in that package?
But our agents are secret! This means that they and no one else should know how many of them exist. We can easily add the
And that's the sort of specialized task that requires the
You can bind this method to the 'Translate' button on the screen and you're done! Anyone can use it. The parts of code marked with the
- private;
- default (package visible);
- protected;
- public.
The private modifier
private
is the most restrictive access modifier. It limits the visibility of data and methods to within a single class.
You know this modifier from the lesson about getters and setters. Remember this example?
We considered it in a previous lesson. We made a serious mistake here: We make our data public, which allowed fellow programmers to access the fields directly and change their values. What's more... these values were assigned without any checks. This means that our program could create a cat named "" with an age of -1000 years and weight of 0. To solve this problem, we used getters and setters, and also used the private modifier to limit access to the data.
Basically, limiting access to fields and implementing getters and setters are the most common examples of how
private
would be used in real work.
In other words, the main purpose of this modifier is to achieve encapsulation in a program.
This doesn't apply only to fields, by the way. Imagine that in your program has a method that implements some VERY complex functionality.
What can we suggest as an example?
Let's say your readDataFromCollider()
method accepts as input a data address, reads data from the Large Hadron Collider in byte format, converts this data into text, writes it to a file, and prints it.
Even a description of the method looks scary, to say nothing of the code :)
To make the code more readable, it would be best to not write all the method's complex logic in one place. Instead, we should break apart the functionality into separate methods.
For example, the readByteData()
method is responsible for reading data, the convertBytesToSymbols()
method converts the data read from the collider into text, the saveToFile()
method saves the received text to a file, and the printColliderData()
method prints our data file.
In the end, our readDataFromCollider()
method will be much simpler:
However, as you'll remember from the lesson about interfaces, the user only gets access to the external interface. And our 4 methods are not part of it. They are helper methods: we created them to improve the readability of the code and to not cram four different tasks into one method. You don't need to give the user access to these methods. If users have access to the
convertBytesToSymbols()
method when working with the collider, they will most likely simply be confused by the method and wonder what it's for. What bytes are converted? Where did they come from? Why convert them to text?
The logic executed in this method is not part of the interface exposed to the user. Only the readDataFromCollider()
method is part of the interface.
So what do we do with these four 'internal' methods? Right! Use the private
modifier to limit access to them.
Doing this allows them to peacefully perform their work inside the class without confusing the user, who doesn't need to know the logic of each individual method.
The package visible modifier
Next on the list is thedefault
modifier, also known as the package visible
modifier. It's not indicated by a keyword, since Java applies it by default to all fields and methods.
If you write the following in your code:
the
x
variable will have this package visible
access.
It's easy to remember what it does. Basically, default
= protected
inheritance :)
Like the protected
modifier, its application is limited. Most often, default
access is used in a package that has some utility classes that don't implement the functionality of all the other classes in the package.
Let's give an example. Imagine that we have a 'services' package. It contains various classes that work with a database. For example, there's a UserService
class that reads user data from the database, a CarService
class that reads car data from the same database, and other classes, each of which works with specific types of objects and reads corresponding data from the database.
But it would be easy for the data in the database to be in one format and we need it in another. Imagine that users' birthdates in the database is stored as <TIMESTAMP WITH TIME ZONE>...
...and instead we need the simplest object — a
java.util.Date
.
To solve this problem, inside the services
package, we can create a special Mapper
class. It will be responsible for converting data from the database into our familiar Java objects. A simple helper class.
We usually declare all classes as public class ClassName
, but this isn't a requirement.
We can declare our helper class simply as class Mapper
. In this case, it still does its job, but it isn't visible to anyone outside the services
package!
And here's the basic reasoning: why would anyone outside a package need to see a helper class that only works with the classes in that package?
The protected modifier
The next most restrictive modifier isprotected
.
Fields and methods marked by the protected
access modifier will be visible:
- within all classes included in the same package as ours;
- within all classes that inherit our class.
protected
than for private
, and they are very specific.
Imagine that we have an AbstractSecretAgent
abstract class that represents a secret agent in some intelligence service, as well as a top_secret
package that contains this class and its descendants. Concrete classes such as FBISecretAgent
, MI6SecretAgent
, MossadSecretAgent
, etc. inherit it.
Inside the abstract class, we want to implement an agent counter. It will increase when a new agent is created somewhere in the program.
package top_secret;
But our agents are secret! This means that they and no one else should know how many of them exist. We can easily add the
protected
modifier to the agent_counter
field. Then instances of other secret agent classes and other classes located in our top_secret
package can get its value.
And that's the sort of specialized task that requires the
protected
modifier :)
The public modifier
And last but not least, thepublic
modifier! You met this modifier on your first day of study on CodeGym the first time you ran public static void main(String[] args)
.
Now that you've studied the lesson about interfaces, its purpose is obvious to you :) After all, the public
modifier was created to give something to users. For example, your program's interface.
Suppose you've written a translator program that can translate Russian text into English. You created a translate(String textInRussian)
method that implements all the necessary logic.
You marked this method with the word public
, and now it's part of the interface:
You can bind this method to the 'Translate' button on the screen and you're done! Anyone can use it. The parts of code marked with the
public
modifier are intended for the end user.
Providing a real-life example, private
is for all processes that occur inside a TV, but public
is for the buttons on the remote control used to manage the TV. What's more, the user doesn't need to know how the television is built or how it works. The remote control is the set of public
-methods: on()
, off()
, nextChannel()
, previousChannel()
, increaseVolume()
, decreaseVolume()
etc.
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.