What is the difference between public, default, protected and private modifiers?

Asked

Viewed 107,040 times

56

What are the differences between modifiers public, default, protected and private when working with inheritance?

There are rules of how and when I should use them when I’m working with heritage and polymorphism?

4 answers

79


There is no rule, only good practice. Let’s go from the beginning.

To begin there are only 3 modifiers (private, protected and public), and with that we have 4 levels of visibility

The levels are what you said: private, default, protected and public

Private: The only class that has access to the attribute is the class itself that defines it, i.e., if a class Pessoa declares a private attribute called nome, only the class Pessoa will have access to it.

Default: You have access to an attribute default (identified by the absence of modifiers) all classes that are in the same package that the class possessing the attribute.

Protected: This is the one that gets the most people, he’s practically the same as default, except that if a class (even if it is outside the package) extends the class with the attribute protected, she will have access to it. Then the access is by parcel and by inheritance.

Public: This is easy, everyone has access :)

The level of visibility involves encapsulation. It is always said as good practice that internal attributes should be private, for external classes should not even know that it exists. What the class exposes are its features, its API, if you prefer. Exposing internal attributes can cause serious security problems. If you have something that is inherent in the implementation, it may change in the future. it should probably be private.

  • 7

    Good answer. I would just add that there is an unofficial "rule": always start with private, and gradually increase depending on the need. Everything you expose to other classes (i.e., anything that isn’t private) is part of your API, so changes to these methods and non-public (especially public) properties can have consequences for consumers.

  • 2

    It is worth adding to this answer that not only attributes are qualified with these modifiers, but also methods. A good practice is to use for the modifier private attributes, since they deal with internal data. If they need to be accessed externally, the use of access methods (getters and setters) keeps control of the class (for validation, for example). For methods that should not be accessed externally, one should seek to use protected. So they can be overwritten if necessary, do not pollute the editors' Intellisense and help in the organization.

  • 1

    And it’s also important to remember that methods and attributes protected in java have public exposure to all classes that are in the same package, regardless of whether they are subclass or not.

  • Excellent remark @bWowk, it makes all the difference what you said. It should be added to the official reply.

  • @bWowk, @Marcelo Rodovalho but that’s what I meant when I said he’s practically the same as default, and explained the difference between them.

36

Translating a great response from the OS in English, by David Segonds:

That one tutorial may be of some help to you.

 Modifier      Class   Package   Subclass   World
──────────────────────────────────────────────────
 public          ✔        ✔         ✔         ✔

 protected       ✔        ✔         ✔         ✘

 no modifier     ✔        ✔         ✘         ✘

 private         ✔        ✘         ✘         ✘
──────────────────────────────────────────────────

And an important comment made to that answer (Edd):

It is probably useful to make it clear that if there is no modifier, the subclass may or may not access the methods/attributes of its superclass depends on the location of the subclass. If the subclass is in a different package than the superclass package, the answer is that it cannot access it. However, it will be able to access them if it is in the same package as the superclass.

Link to the original here

15

These modifiers are responsible for access control members of the class (fields and methods), also known as encapsulation. The idea is to assist in the creation of a stable API, but at the same time give room for the code to change in the future (in other words, separate well what is specification from what is implementation).

The virtues of encapsulation are debatable, there are languages that look good without any access control (i.e. all code can access anything), but anyway the reduction in coupling of the various components of a system is a desirable goal (greater ease of evolution, and potentially fewer bugs). In particular projects developed by numerous and/or inexperienced teams, it is not good to expose too much code that is not to be touched (or simply accessed) by others who are not responsible for certain functionality. In the remainder of this answer, I will take on this type of scenario, others - for example, projects developed by one person - may benefit from a more "relaxed access control".

The other answers already give a good overview. I will approach each modifier with a little more detail:

private

Private members are those fields and methods which concern only the implementation of the class, and which do not matter who uses it. Deciding what matters or not can be difficult, but some questions can help guide the decision-making process:

  • Is this member part of the class contract? If it is, it cannot be private...
  • If someone uses "wrong" this member (change field values, call the method at the wrong time or with the wrong parameters, etc.) will the consequences be negative and/or unpredictable? If so, it is a good candidate to be private.
  • Do you intend to change this member in the future? Do you have a better idea of implementation that you cannot put into practice yet, or are you not 100% sure that this is the way things have to be? Putting it as private gives you more freedom to change in the future, although there are many people using your class.

There are those who recommend that all camps be private, and that’s a good thing beginning when designing a class. In the future, changing your mind may increase the exposure of a private member at will, but diminish the exposure in general causes problems (potentially breaking the code that uses your class). So I would say that in doubt, make everything private...

public

Public members are those fields and methods that are part of the class contract. If the class represents a guy (whether a concrete implementation of an existing type, or a subtype of another), your contract is the API that consumers have at their disposal to use the class.

After a class is made available, or published, it must be assumed that any public member of the class may be being used by other codes beyond their control. Thus, it is important never change/remove a public member throughout the product lifecycle within the versions expected to reverse compatibility (backward Compatibility). If necessary mark a member as obsolete (deprecated), still it is desirable to give appropriate maintenance to it - making sure that it keeps working in the new versions and with the expected behavior according to the time it was written (in certain limited situations, even with the same bugs).

When deciding what to make public, look at all that is needed (for example, inherited classes and implemented interfaces) and add what you find useful (in reasonable cases and use). Leave out everything else. In particular, if you feel that some part of the code will have to be changed in the future, do not make it public unless it is extremely necessary.

protected

Its main purpose is to assist in the class extension (inheritance) process. In principle, a field/method protected could very well be private: it handles implementation details, but not the class contract. However, although such details are not relevant to who uses the class, they can be relevant to those who try to create subtypes of the class (since subtypes share much of the implementation, and therefore are interested in the details).

While private fields are not part of any contract - and therefore can be changed at the pleasure of the programmer in future versions of the class - both public and protected fields should ideally have a stable API. Of course you can make one or the other obsolete if necessary (that’s why the deprecated exists), but one must be aware that this can break code that uses them. So, if you decide to expose implementation details to subclasses, make sure these details are stable, that they are unlikely to be changed in the future.

"pattern" (default) or "package" (package-protected)

This modifier (expressed by the absence of the other three modifiers) is a somewhat "strange" case: other classes within the same package can access the default fields, but the rest of the code cannot. It is difficult to determine the exact usefulness of it, but I think it assists the evolution of the system:

When you start writing a program, you can’t always anticipate exactly what is stable and what is not, what should go to the API and what should not. The program is not structured optimally, and classes access members of each other that they should not. That shouldn’t happen, but it does, and at that time of development this is not a big problem - after all the code has not yet been made available, only the author has access to it, and it is expected that he will be careful not to misuse the classes he wrote himself...

Forcing the programmer to choose an access level right away, before he even "feels" what the code should or should not do, seems counterproductive. Even after a certain level of stability, it is expected that whoever wrote a set of codes (the packages are usually made by the same authors, or at least by the same organization) make fewer mistakes and/or be able to change their components whenever one of them changes and negatively affects the others.

If so, I would say use it "whenever in doubt", but get rid of it as soon as I can determine the best modifier to use. With experience, the use of default gets more and more rare, until it reaches the point that it is not necessary at all.

  • What do you mean by "class contract"?

  • @Guilhermeumemura the concept comes from here: Programming by Contract. If in doubt, I suggest to open a separate question about it, I haven’t participated in this site for a while, but others can give a good answer (since it is a common topic in OO).

8

Suppose you have a class Animal and a subclass Gato, who inherits from Animal.

In class Gato, you can call all methods Animal declared as public or protected, and if the classes are in the same package, the default methods. That is, Gato does not call the methods private of Animal. The same reasoning applies to attributes.

You can also overwrite (override), at Gato, the methods public and protected of Animal and, if in the same package, also the default methods.

Note that you may have, at Gato, a method with the same signature as a method private of Animal, but in this case it is a new method, not a new version of the Animal. This is clear in this example:

class Animal {
  protected void metodoProtected() {
    System.out.println("animal protected");
  }
  private void metodoPrivate() {
    System.out.println("animal private");
  }
}

class Gato extends Animal {
  protected void metodoProtected() {
    System.out.println("gato protected");
  }
  private void metodoPrivate() {
    System.out.println("gato private");
  }
}

Now, if you have a reference like Animal for an object of the type Gato, and call:

Animal animal = new Gato();
animal.metodoProtected();
animal.metodoPrivate();

The result will be

gato protected
animal private

As the private method of Animal was not written by Gato, is he who is called when you have a reference of type Animal.

Good practice:

  • if the method should be used by other classes (which are not subclasses), use public;
  • otherwise, if you want your subclasses to change some behavior, encapsulate the behavior in a method protected;
  • if the method deals with an implementation detail and you don’t want anyone to modify it (not even the subclasses), use private.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.