1

I was doing some reading here. The user suggested that

if you plan on subclassing and want the validation setter available, declare it protected final instead of private.

why declare a method protected final when I could declare it private and have the constructor in the base class set the variables.

Example:

    public class Person {


        private String firstName;
        private String lastName;

        public Person(String firstname,String lastname) throws InvalidDataException
        {
            setFirstname( firstname);
            setLastname(lastname);
        }


        public void personFirstName(String firstName) throws InvalidDataException { 
            setFirstname(firstName);
        }

        public void personLastName(String lastname) throws InvalidDataException {

            setLastname(lastname);
        }

        public String getFirstName() {
            return firstName;
        }

        public String getlasttName()
        {
            return lastName;
        }

        private void setFirstname(String firstname) throws InvalidDataException{
             if( firstname == null ||firstname.length() < 1) {
                    throw new InvalidDataException("First Name Cannot be Empty");
             }
              this.firstName=firstname; 

        }

        private void setLastname(String lastname) throws InvalidDataException {

             if( lastname == null ||lastname.length() < 1) {
                    throw new InvalidDataException("Last Name Cannot be Empty");

             }

             this.lastName = lastname;
        }

    }

public class Professor extends Person {


    private String  professorID;



    public Professor(String professorID,String firstname, String lastname) throws InvalidDataException {
        super(firstname, lastname);
        // TODO Auto-generated constructor stub
        setProfessorID(professorID);
    }

    public void setID(String professorID) throws InvalidDataException{

        setProfessorID(professorID);
    }

    public String getID()
    {
        return this.professorID;
    }

    private void setProfessorID(String ID) throws InvalidDataException{
         if( ID == null ||ID.length() < 1) {
                throw new InvalidDataException("ID Cannot be Empty");
         }
          this.professorID=ID; 

    }

    public void printData()
    {
         System.out.println("Professor ID: " + this.getID() + " First Name: " + this.getFirstName() + " Last Name: " + this.getlasttName());
    }

}

In what situation would I want to declare the private methods in Person to be protected final? My subclass Professor can access them through the constructor in the base class.

Community
  • 1
  • 1
  • 2
    Should the names ever change after initialization? What happens if a professor gets married? – nhgrif Mar 01 '15 at 15:34
  • @nhgrif - Good Point. So the protected method allows me to change a value, without re-declaring the object, correct? –  Mar 01 '15 at 15:35

3 Answers3

3

protected

The protected key word is an access modifier that allows subclasses to access this resource. In this case, the method.

final

The final key word is a polymorphic restriction that prevents subclasses from redefining a given resource. Again, in this case, the method.

With these definitions in mind, this creates a validation method that the subclass can still access without being able to change it. In short, no subclasses can violate the terms of the validation. By just putting the calls in the constructor, this means that subclasses can not make validation calls anywhere else. They have to create a new object every time they want to test, which is obviously not desirable.

Doing it this way makes it more testable, but allows subclasses as much flexibility as they should be permitted while not breaking the validation rules.

christopher
  • 26,815
  • 5
  • 55
  • 89
  • Thank you so much for this explanation. So really, leave it protected final, that would be the best practice? –  Mar 01 '15 at 15:43
  • If you think that the type of validation is never going to change, then yes. For example, everyone has a name, so if your validation is `if(name != null)`, then yeah. But if, for example, your validation says that everyone has two names, split by a space, you might fall into problem with names from different cultures. It's dependant on what the conditions *are*. – christopher Mar 01 '15 at 15:44
  • So, what you're saying is in some cases, depending on certain conditions, I'll want it protected, but not final, to allow the method to be shared by subclasses, and overriden. Correct? –  Mar 01 '15 at 15:46
  • Correct. By making it protected, you give the subclasses *access* without license to change it. So if you feel like the conditions will *never* change (and be careful with that word), then make it final. – christopher Mar 01 '15 at 15:53
1

That's for the case where the subclass should be able to set the value. Since you can't foresee the subclasses, you better make the assumption that all values can be set by a third value. For instance in some culture's a women takes the name of her husband. For instance:

public class Women extends Person {

    public void marry (Person person) {
        setLastName(person.getLastName());
    }


}

The book probably suggests not to make the field protected, after all each class must guarantee that its own state is valid. By thus rewriting a validator yourself, you could invalidate the state from the super class point of view.

It is for instance reasonable to assume that a persons name doesn't contain digits. You can implement this logic in the setter-validator. If you however declare the field protected, one could overrule this.

Making the method public, as you did, is probably not adviseable, at least not in a general case. That would imply every object has the right to set a persons name.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
1

Besides extending, the use for protected can be for Managing Classes.

See, protected does not mean only a child class has access to the field in question. But any class within the same package.

Say you have an abstract class Entity

And another class SpecificEntity1 extends Entity

And another class SpecificEntity2 extends Entity

but you want a way to keep track of all entities.

What you do is you make the constructors for the specific classes protected

put all of the classes in the same package and create another class in that package like EntityManager with a createEntity method. that way you can only create your entities using that class outside of the package.

Dima Maligin
  • 1,386
  • 2
  • 15
  • 30