Is the protected modifier a " white elephant"?

Are there clear rules on when to use each of these when making classes and interfaces and dealing with inheritance?

Replay

The official tutorial may be of some use to you.

            | Class | Package | Subclass | World
————————————+———————+—————————+——————————+———————
public      |  y    |    y    |    y     |   y
————————————+———————+—————————+——————————+———————
protected   |  y    |    y    |    y     |   n
————————————+———————+—————————+——————————+———————
no modifier |  y    |    y    |    n     |   n
————————————+———————+—————————+——————————+———————
private     |  y    |    n    |    n     |   n

y: accessible
n: not accessible

(Caveat: I am not a Java programmer, I am a Perl programmer. Perl has no formal protections which is perhaps why I understand the problem so well :) )

Private

Like you'd think, only the class in which it is declared can see it.

Package Private

Can only be seen and used by the package in which it was declared. This is the default in Java (which some see as a mistake).

Protected

Package Private + can be seen by subclasses or package member.

Public

Everyone can see it.

Published

Visible outside the code I control. (While not Java syntax, it is important for this discussion).

C++ defines an additional level called "friend" and the less you know about that the better.

When should you use what? The whole idea is encapsulation to hide information. As much as possible you want to hide the detail of how something is done from your users. Why? Because then you can change them later and not break anybody's code. This lets you optimize, refactor, redesign and fix bugs without worry that someone was using that code you just overhauled.

So, rule of thumb is to make things only as visible as they have to be. Start with private and only add more visibility as needed. Only make public that which is absolutely necessary for the user to know, every detail you make public cramps your ability to redesign the system.

If you want users to be able to customize behaviors, rather than making internals public so they can override them, it's often a better idea to shove those guts into an object and make that interface public. That way they can simply plug in a new object. For example, if you were writing a CD player and wanted the "go find info about this CD" bit customizable, rather than make those methods public you'd put all that functionality into its own object and make just your object getter/setter public. In this way being stingy about exposing your guts encourages good composition and separation of concerns

Personally, I stick with just "private" and "public". Many OO languages just have that. "Protected" can be handy, but it's really a cheat. Once an interface is more than private it's outside of your control and you have to go looking in other people's code to find uses.

This is where the idea of "published" comes in. Changing an interface (refactoring it) requires that you find all the code which is using it and change that, too. If the interface is private, well no problem. If it's protected you have to go find all your subclasses. If it's public you have to go find all the code which uses your code. Sometimes this is possible, for example if you're working on corporate code that's for internal use only it doesn't matter if an interface is public. You can grab all the code out of the corporate repository. But if an interface is "published", if there is code using it outside your control, then you're hosed. You must support that interface or risk breaking code. Even protected interfaces can be considered published (which is why I don't bother with protected).

Many languages find the hierarchical nature of public/protected/private to be too limiting and not in line with reality. To that end there is the concept of a trait class, but that's another show.

Easy rule. Start with declaring everything private. And then progress towards public as the needs arises and design warrant it.

When exposing members ask yourself if you are exposing representation choices or abstraction choices. The first is something you want to avoid as it will introduce to much dependencies on the actual representation rather than it's observable behavior.

As a general rule I try to avoid overriding method implementations by sub-classing, it's to easy to screw up the logic. Declare abstract protected methods if you intend for it to be overridden.

Also use the @Override annotation when overriding to keep things from breaking when you refactor.

                | highest precedence <---------> lowest precedence
*———————————————+————————————————+———————————+———————————————+———————
 \ xCanBeSeenBy | this           | any class | this subclass | any
  \__________   | class          | in same   | in another    | class
             \  | nonsubbed      | package   | package       |
Modifier of x \ |                |           |               |
————————————————*————————————————+———————————+———————————————+———————
public          |               |          |              |
————————————————+————————————————+———————————+———————————————+———————
protected       |               |          |              |   ✘
————————————————+————————————————+———————————+———————————————+———————
package-private |                |           |               |
(no modifier)   |               |          |    ✘          |   ✘
————————————————+————————————————+———————————+———————————————+———————
private         |               |    ✘      |    ✘          |    ✘

It's actually a bit more complicated than a simple grid shows. The grid tells you whether an access is allowed, but what exactly constitutes an access? Also, access levels interact with nested classes and inheritance in complex ways.

The "default" access (specified by the absence of a keyword) is also called package-private. Exception: in an interface, no modifier means public access; modifiers other than public are forbidden. Enum constants are always public.

Summary

Is an access to a member with this access specifier allowed?

  • Member is private: Only if member is defined within the same class as calling code.
  • Member is package private: Only if the calling code is within the member's immediately enclosing package.
  • Member is protected: Same package, or if member is defined in a superclass of the class containing the calling code.
  • Member is public: Yes.

What access specifiers apply to

Local variables and formal parameters cannot take access specifiers. Since they are inherently inaccessible to the outside according to scoping rules, they are effectively private.

For classes in the top scope, only public and package-private are permitted. This design choice is presumably because protected and private would be redundant at the package level (there is no inheritance of packages).

All the access specifiers are possible on class members (constructors, methods and static member functions, nested classes).

Related: Java Class Accessibility

Order

The access specifiers can be strictly ordered

public > protected > package-private > private

meaning that public provides the most access, private the least. Any reference possible on a private member is also valid for a package-private member; any reference to a package-private member is valid on a protected member, and so on. (Giving access to protected members to other classes in the same package was considered a mistake.)

Notes

  • A class's methods are allowed to access private members of other objects of the same class. More precisely, a method of class C can access private members of C on objects of any subclass of C. Java doesn't support restricting access by instance, only by class. (Compare with Scala, which does support it using private[this].)
  • You need access to a constructor to construct an object. Thus if all constructors are private, the class can only be constructed by code living within the class (typically static factory methods or static variable initializers). Similarly for package-private or protected constructors.
    • Only having private constructors also means that the class cannot be subclassed externally, since Java requires a subclass's constructors to implicitly or explicitly call a superclass constructor. (It can, however, contain a nested class that subclasses it.)

Inner classes

You also have to consider nested scopes, such as inner classes. An example of the complexity is that inner classes have members, which themselves can take access modifiers. So you can have a private inner class with a public member; can the member be accessed? (See below.) The general rule is to look at scope and think recursively to see whether you can access each level.

However, this is quite complicated, and for full details, consult the Java Language Specification. (Yes, there have been compiler bugs in the past.)

For a taste of how these interact, consider this example. It is possible to "leak" private inner classes; this is usually a warning:

class Test {
    public static void main(final String ... args) {
        System.out.println(Example.leakPrivateClass()); // OK
        Example.leakPrivateClass().secretMethod(); // error
    }
}

class Example {
    private static class NestedClass {
        public void secretMethod() {
            System.out.println("Hello");
        }
    }
    public static NestedClass leakPrivateClass() {
        return new NestedClass();
    }
}

Compiler output:

Test.java:4: secretMethod() in Example.NestedClass is defined in an inaccessible class or interface
        Example.leakPrivateClass().secretMethod(); // error
                                  ^
1 error

Some related questions:

  • Java - Method accessibility inside package-private class?

As a rule of thumb:

  • private: class scope.
  • default (or package-private): package scope.
  • protected: package scope + child (like package, but we can subclass it from different packages). The protected modifier always keeps the "parent-child" relationship.
  • public: everywhere.

As a result, if we divide access right into three rights:

  • (D)irect (invoke from a method inside the same class).
  • (R)eference (invoke a method using a reference to the class, or via "dot" syntax).
  • (I)nheritance (via subclassing).

then we have this simple table:

Is the protected modifier a " white elephant"?

In very short

  • Public are accessible from everywhere.
  • Protected are accessible by the classes of the same package and the subclasses residing in any package.
  • Default are accessible by the classes of the same package.
  • private are accessible within the same class only.

Here's a better version of the table. (Future proof with a column for modules.)

Is the protected modifier a " white elephant"?


Explanations

  • A private member is only accessible within the same class as it is declared.
  • A member with no access modifier is only accessible within classes in the same package.
  • A protected member is accessible within all classes in the same package and within subclasses in other packages.
  • A public member is accessible to all classes (unless it resides in a module that does not export the package it is declared in).

Which modifier to choose?

Access modifiers is a tool to help you to prevent accidentally breaking encapsulation(*). Ask yourself if you intend the member to be something that's internal to the class, package, class hierarchy or not internal at all, and choose access level accordingly.

Examples:

  • A field long internalCounter should probably be private since it's mutable and an implementation detail.
  • A class that should only be instantiated in a factory class (in the same package) should have a package restricted constructor, since it shouldn't be possible to call it directly from outside the package.
  • An internal void beforeRender() method called right before rendering and used as a hook in subclasses should be protected.
  • A void saveGame(File dst) method which is called from the GUI code should be public.

(*) What is Encapsulation exactly?

The most misunderstood access modifier in Java is protected. We know that it's similar to the default modifier with one exception in which subclasses can see it. But how? Here is an example which hopefully clarifies the confusion:

  • Assume that we have 3 classes; Grandfather, Father and Son:
    package grandfatherpackage;
    
    public class Grandfather
    {
    
    }
    
    -------------------------------------------
    
    package fatherpackage;
    
    public class Father extends Grandfather
    {
    
    }
    
    -------------------------------------------
    
    package sonpackage;
    
    public class Son extends Father
    {
    
    }
    
    
  • Let's add a protected method foo() to Grandfather.
    package grandfatherpackage;
    
    public class Grandfather
    {
        protected void foo(){}
    }
    
    
  • The method foo() can be called in 3 contexts:
    1. Inside a class that is located in the same package where foo() is defined, which is grandfatherpackage:
      package grandfatherpackage;
      
      public class SomeClass
      {
          public void someMethod() throws Exception
          {
              Father f = new Father();
              f.foo();
      
              Son s = new Son();
              s.foo();
          }
      }
      
      
    2. Inside a subclass, on the current instance this:
      package fatherpackage;
      
      public class Father extends Grandfather
      {
          public void fatherMethod()
          {
              this.foo();
          }
      }
      
      -------------------------------------------
      
      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod()
          {
              this.foo();
          }
      }
      
      
    3. On an reference whose type is the same class:
      package fatherpackage;
      
      public class Father extends Grandfather
      {
          public void fatherMethod()
          {
              Father f = new Father();
              f.foo();
          }
      }
      
      -------------------------------------------
      
      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod()
          {
              Son s = new Son();
              s.foo();
          }
      }
      
      
  • Regarding the third situation, it won't compile if the reference is of type of the parent class:
    package fatherpackage;
    
    public class Father extends Grandfather
    {
        public void fatherMethod()
        {
            Grandfather f = new Grandfather();
            g.foo(); // compilation error
    
            Grandfather g = new Father();
            g.foo(); // compilation error
        }
    }
    
    -------------------------------------------
    
    package sonpackage;
    
    public class Son extends Father
    {
        public void sonMethod()
        {
            Grandfather g = new Grandfather();
            g.foo(); // compilation error
    
            Grandfather s = new Son();
            s.foo(); // compilation error
    
            Father f = new Father();
            f.foo(); // compilation error
    
            Father ff = new Son();
            ff.foo(); // compilation error
        }
    }
    
    

Private

  • Methods,Variables and Constructors

Methods, Variables and Constructors that are declared private can only be accessed within the declared class itself.

  • Class and Interface

Private access modifier is the most restrictive access level. Class and interfaces cannot be private.

Note

Variables that are declared private can be accessed outside the class if public getter methods are present in the class. Variables, methods and constructors which are declared protected in a superclass can be accessed only by the subclasses in other package or any class within the package of the protected members' class.


Protected

  • Class and Interface

The protected access modifier cannot be applied to class and interfaces.

Methods, fields can be declared protected, however methods and fields in a interface cannot be declared protected.

Note

Protected access gives the subclass a chance to use the helper method or variable, while preventing a nonrelated class from trying to use it.


Public

A class, method, constructor, interface etc declared public can be accessed from any other class.

Therefore fields, methods, blocks declared inside a public class can be accessed from any class belonging to the Java Universe.

  • Different Packages

However if the public class we are trying to access is in a different package, then the public class still need to be imported.

Because of class inheritance, all public methods and variables of a class are inherited by its subclasses.


Default -No keyword:

Default access modifier means we do not explicitly declare an access modifier for a class, field, method, etc.

  • Within the same Packages

A variable or method declared without any access control modifier is available to any other class in the same package. The fields in an interface are implicitly public static final and the methods in an interface are by default public.

Note

We cannot Override the Static fields.if you try to override it does not show any error but it doesnot work what we except.

Related Answers

  • Overriding static methods in java

References links

http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html http://www.tutorialspoint.com/java/java_access_modifiers.htm

Private : Limited Access to Class only

Default(No Modifier) : Limited Access to Class and Package

Protected: Limited Access to Class,Pacakge and Subclasses(Inside and Outside Package both)

Public: Accessible to Class,Package(All),Subclasses...In short everywhere

Access Modifiers are there to restrict access at several level.

Public : it is basically as simple as you can access from any class either that is in same package or not.

To access if you are in same package you can access directly but if you are in other package then you can create object of class.

Default : it is accessible in same package from any of the class of package.

to access you can create object of class. but you can not access this variable outside of the package.

Protected : you can access variables in same package as well as subclass in any other package. so basically it is default + Inherited behavior.

To access protected field defined in base class you can create object of child class.

Private : it can be access in same class.

In non-static methods you can access directly because of this reference (also in constructors)but to access in static methods you need to create object of the class.

The difference can be found in the links already provided but which one to use usually comes down to the "Principle of Least Knowledge". Only allow the least visibility that is needed.

Visible to the package. the default. No modifiers are needed.

Visible to the class only (private).

Visible to the world (public).

Visible to the package and all subclasses (protected).

Variables and methods can be declared without any modifiers that is called Default examples:

String name="john";
public int age(){
return age;
}

Private Access Modifier - private: Methods, Variables and Constructors that are declared private can only be accessed within the declared class itself.Private access modifier is the most restrictive access level. Class and interfaces cannot be private.

Variables that are declared private can be accessed outside the class if public getter methods are present in the class.

Using the private modifier is the main way that an object encapsulates itself and hide data from the outside world. examples:

Public class Details{
private String name;
public void setName(String n){
this.name=n;
}
public String getName(){
return this.name;
}
}

Public Access Modifier - public: A class, method, constructor, interface etc declared public can be accessed from any other class. Therefore fields, methods, blocks declared inside a public class can be accessed from any class belonging to the Java Universe.

However if the public class we are trying to access is in a different package, then the public class still need to be imported.

Because of class inheritance, all public methods and variables of a class are inherited by its subclasses. example:

public void cal(){

}

Protected Access Modifier - protected: Variables, methods and constructors which are declared protected in a superclass can be accessed only by the subclasses in other package or any class within the package of the protected members' class.

The protected access modifier cannot be applied to class and interfaces. Methods, fields can be declared protected, however methods and fields in a interface cannot be declared protected.

Protected access gives the subclass a chance to use the helper method or variable, while preventing a nonrelated class from trying to use it.

class Van{

    protected boolean speed(){

    }
}
class Car{
    boolean speed(){
    }

}

David's answer provides the meaning of each access modifier. As for when to use each, I'd suggest making public all classes and the methods of each class that are meant for external use (it's API), and everything else private. You'll develop over time a sense for when to make some classes package-private and when to declare certain methods protected for use in subclasses.

this page writes well about the protected & default access modifier

.... Protected: Protected access modifier is the a little tricky and you can say is a superset of the default access modifier. Protected members are same as the default members as far as the access in the same package is concerned. The difference is that, the protected members are also accessible to the subclasses of the class in which the member is declared which are outside the package in which the parent class is present. But these protected members are “accessible outside the package only through inheritance“. i.e you can access a protected member of a class in its subclass present in some other package directly as if the member is present in the subclass itself. But that protected member will not be accessible in the subclass outside the package by using parent class’s reference. ....

Public Protected Default and private are access modifiers.

They are meant for encapsulation, or hiding and showing contents of the class.

  1. Class can be public or default
  2. Class members can be public, protected, default or private.

Private is not accessible outside the class Default is accessible only in the package. Protected in package as well as any class which extends it. Public is open for all.

Normally, member variables are defined private, but member methods are public.

I just want to address a detail that is extremely commonly got wrong, including by most of the answers on this page. "Default" access (when no access modifier is present) is not always the same as package-private. It depends on what the thing is.

  • Non-member types (that is, classes, enums, interfaces, and annotation types not declared inside another type) are package-private by default. (JLS §6.6.1)
  • Class members and constructors are package-private by default. (JLS §6.6.1)
  • Enum constructors are private by default. (Indeed, enum contructors must be private, and it is an error to try to make them public or protected). Enum constants are public, and do not allow any access specifier. Other members of enums are package-private by default. (JLS §8.9)
  • All members of interfaces and annotation types are public by default. (Indeed, members of interfaces and annotation types must be public, and it is an error to try to make them private or protected.) (JLS §9.3 to 9.5)

public - accessible from anywhere in the application, default - accessible from package, protected - accessible from package and sub-classes in other package as well, private - accessible from its class only.

  • Visible to the package. the default. No modifiers are needed.
  • Visible to the class only;private.
  • Visible to the world;public.
  • Visible to the package and all subclasses;protected.

So let's talk about Access Control and Inheritance The following rules for inherited methods are,

  • Methods declared public in a superclass also must be public in all subclasses.
  • Methods declared protected in a superclass must either be protected or public in subclasses; they cannot be private.
  • Methods declared without access control (no modifier was used) can be declared more private in subclasses.
  • Methods declared private are not inherited at all, so there is no rule for them.
Category: java Time: 2008-10-18 Views: 0

Related post

iOS development

Android development

Python development

JAVA development

Development language

PHP development

Ruby development

search

Front-end development

Database

development tools

Open Platform

Javascript development

.NET development

cloud computing

server

Copyright (C) avrocks.com, All Rights Reserved.

processed in 0.133 (s). 12 q(s)