7

I'm currently in a Java-based university class and for coding samples the professor is using protected fields for the subclasses to access.

I asked if this was bad practice and was told it is normal. Is this true, why not use setters and getters for abstract methods? I thought it was always best practice to restrict as much information as possible unless required otherwise.

I tested out using setters and getters with abstract parent and it works fine for abstract parent classes that are subclassed. Although abstract classes cannot be instantiated, they can still be used to create objects when a subclass is instantiated as far as I understand.

Here is a short example:

public abstract class Animal {
    protected int height;
}

public class Dog extends Animal {
    public Dog() {
        height = 6;
    }
}

public class Cat extends Animal {
    public Cat() {
        height = 2;
    }
}

As opposed to using:

public abstract class Animal {
    private int height;

    public getHeight() {
        return height;
    }

    public setHeight(int height) {
        this.height = height;
    }
}

public class Dog extends Animal {
    public Dog() {
        setHeight(6);
    }
}

public class Cat extends Animal {
    public Cat() {
        setHeight(2);
    }
}
f1sh
  • 11,489
  • 3
  • 25
  • 51
Adam Thompson
  • 3,278
  • 3
  • 22
  • 37
  • 2
    Post some code. It's hard to follow your argument. – Robert Moskal Oct 15 '15 at 01:59
  • Added some brief code, let me know if it is not illustrative enough. – Adam Thompson Oct 15 '15 at 02:06
  • If you read Java language source code, you will find a lot uses for protected fields – dragon66 Oct 15 '15 at 02:41
  • I don't doubt that protected fields are useful, but I'm just wondering if there is a reason to use protected fields in this case with abstract class? Or if private + setters/getters is better? – Adam Thompson Oct 15 '15 at 02:42
  • Even though you achieved the same goal with your second example, you added public API which the first example doesn't expose. Your new implementation is mutable. – dragon66 Oct 15 '15 at 03:06
  • @dragon66 he could have easily made the setter `protected` and he probably meant to. The protected height is mutable to anything in the same package as well as overriding classes. – Adam Gent Oct 15 '15 at 03:28
  • @AdamGent: I believe he could change to other things. But I am talking about the current state – dragon66 Oct 15 '15 at 12:15

2 Answers2

6

While you can certainly do both ways the protected field way is less desirable and I would argue less idiomatic particularly if this is library code that you plan to share.

You can see this in the Java Collections API as well as Guava. You will be hard pressed to find Abstract classes that have protected fields (let alone any fields).

That being said there are always exceptions and you are not always writing library code (ie public api).

Here is my opinion on protected and/or private fields and abstract classes. If you are going to do it than make a constructor that takes the initial values:

public abstract class Animal {
    private int height;
    public Animal(int height) { this.height = height; }
    public int getHeight() { return this.height }
}

public class Cat extends Animal {
    public Cat() {
        super(2);
    }
}

Now your subclasses are required to set height to something as they have to call the constructor that takes height.

Webleeuw
  • 7,222
  • 33
  • 34
Adam Gent
  • 47,843
  • 23
  • 153
  • 203
  • This is what I am looking for. So in this example that you gave, you would still be better off using private instead of protected? I'm really just trying to figure out if private + getters/setters is a better alternative than protected fields in abstract classes. Thank you! – Adam Thompson Oct 15 '15 at 03:41
  • 2
    Your instructor is also probably trying to teach you traditional OOP which does involve lots of state being inherited particularly in some frameworks like Swing. In modern Java this is eschewed. Abstract classes are used to share behavior and not state (the GOF book also favors this). Inheritance of state is pretty nasty unless its getter/setter objects (aka POJO) which is done for DRY reasons. That is behavior objects don't typically have a ton of getters and setters but data objects do. – Adam Gent Oct 15 '15 at 03:48
  • 1
    So the short of it is yes. Prefer private overy protected for fields. – Adam Gent Oct 15 '15 at 04:16
  • 1
    Why do you keep the field protected instead of private? – dragon66 Oct 15 '15 at 12:20
  • Valid point, dragon66. Sorry to up a 4 year old post, but I edited Adam Gent's code accordingly. – Webleeuw May 23 '19 at 08:54
  • In this example, I'd make the "private int height" final, so "private final int height", just because I feel like it's good practice to make everything final unless it needs to be changed at some point. But if it's final, is there a benefit to making it private instead of protected? Say I want to write a method in Cat that does some computation using height. I know it can use getHeight(), but is that better than just giving it access to height (which is final now) by making it protected? – Brent212 Sep 17 '20 at 00:27
  • (Sorry, comment was too long for one, so here's the rest) What if you don't want public access to height? Do you make a protected method getHeight(), or do you just make the final int height protected to cut down on code? – Brent212 Sep 17 '20 at 00:27
1

In your first example, only subclasses of Animal can access the protected field height. In you second example, any class whatsoever can manipulate the field height indirectly via the public setter method. See the difference?

Darren
  • 722
  • 4
  • 12
  • He could easily make the setter protected as well. – Adam Gent Oct 15 '15 at 03:08
  • ok, I see where you are coming from. Aside from the security aspect, if you made access to the abstract class data available via a getter and setter, then you could choose to implement and even re-implement the abstract class implementation any way you want without breaking the subclass implementation. – Darren Oct 15 '15 at 03:14