btse
btse

Reputation: 8021

Proper way to declare field that needs to exist in sub-classes?

Say I have a class Animal and then a bunch of sub-classes that extend Animal. Say I want to have a common field called name that should also exist in each child class. What is the proper way to include and initialize this field in each sub-class?

1) Declare the field in the parent as protected, and then initialize it inside of each sub-class. If I do it this way, is it proper to refer to the field as super.variable or simply variable? Personally to me, using super makes it more obvious that the field is declared in the parent. (This is what I am currently doing)

2) Declare the field in the parent as private and then create getters and setters to access the field

3) Just declare and initialize the same variable in each sub-class

4) Another method I'm missing?

Thanks for the help. I understand this question is fairly basic, but I'm curious of what the most proper style is.

Edit:

I'm not to sure if you guys will see this, but here is a follow up question.

Is there any good way to ensure that the sub-classes initialize the field?

Upvotes: 3

Views: 1206

Answers (5)

Kevin Bowersox
Kevin Bowersox

Reputation: 94499

I think it depends on the situation. If the name field should be publicly accessible, I would declare the field as private and then make public get/set methods. Sometimes you want to expose fields on the base class as part of the public interface of the derived classes.

If the name field should only be used inside the derived classes I would just go with a protected field.

If you want to be sure that a subclass initializes a field add a parameter in the base class constructor, then initialize the field in the base class using the argument supplied by the derived classes constructor.

Upvotes: 2

Luca Basso Ricci
Luca Basso Ricci

Reputation: 18413

I usually using option 2 (private + accessors - protected,not necessary public) to have a chance to customize variable access.

About your edit: Force in constructor name if it is a mandatory requirement

Animal(String name) {
    this.name = name;
}

or

String getName()  {
    if(null == name){
        name = initializeName();
    }
    return name;
}

and make initializeName() abstract

Upvotes: 1

Thomas W
Thomas W

Reputation: 14154

I always make fields protected fields, since this helps debuggability & extensibility, and put public getters & setters on them to make a 'property'.

(Private fields in various open-source libraries, Swing components etc have repeatedly been a hindrance to me when trying to do quite legitimate debugging/ extension engineering. So I'm fairly anti- them.)

If I'm concerned about traceability, where there is possible behaviour or errors involved (such as values being got & cached), I might access the variable in subclasses via the getter.

I always use this.name when writing to variables -- it works well for code clarity, and it simplifies parameter-naming in setters. (Use just name for the parameter & this.name for the field.)

I don't use this when reading variables -- it's the writes I want to be clear about. For collections, I suffix the field with List or map or whatever ie childList -- but the parameter and locals are "children".

I never use super when referring to variables. Super would only make sense to disambiguate inherited & declared variables with the same name, which you can legally do -- but is almost guaranteed to be erroneous for code style, clarity & tends to lead to bugs.


I also like to make most properties mutable -- rather than settable only at construction. This helps if you ever want to use Hibernate, or persist the data. Over-reliance on constructor initialization tends to evolve into difficulties -- large & brittle call-signatures, inability to use the class for partly-formed data or "special value" answers, and order-of-init problems.

Upvotes: 2

The answer depends on whether you need to control access to that field for correctness (e.g., to make sure that some other field gets updated at the same time). If it's okay for subclasses to twiddle the field directly, then just use protected. If you need to perform additional checks or actions whenever the field is set, you should make it private to the superclass and make the subclass use the setter to ensure your logic is run. You shouldn't duplicate the field if you know that it'll always be needed; if you're not sure, then you should consider using an interface Animal and putting the field on an AbstractAnimal implements Animal.

In Java, you don't use super for anything except to call the superclass's version of a method. Just access protected fields directly; that's what they're there for, and your development environment will keep track of where they're declared if you need to know.

Upvotes: 4

Thilo
Thilo

Reputation: 262834

I vote for 2:

Create a private field, and have setters and getters (which can be protected to make them accessible only to subclasses).

Other options if you don't need a setter (just a getter):

4) Abstract getter and leave it up to the subclass how to implement it

5) private final field, set by abstract class constructor, and a getter.

Upvotes: 2

Related Questions