The use of protected member variables from child class and abstract parent - java

According to our professor, the use of protected visibility should be avoided at all costs. However, I'm a little puzzled as to why. Say We have this for example:
public abstract class Animal {
private int maxSpeed;
public Animal() {}
public abstract void setMaxSpeed();
}
Where each Animal would have a max speed that would need to be defined later in the child class. However, throwing this in:
public class Tutrle extends Animal {
public Tutrle() {
}
#Override
public void setMaxSpeed() {
}
}
There is no way to be able to access the maxSpeed variable from within the overridden setMaxSpeed() method. Although a solution would be to set maxSpeed via the constructor of the Animal class, wouldn't be better to set the maxSpeed variable to protected and have it accessible to all child sub-classes to be defined later?

Since the maxSpeed member is defined in the Animal class, it makes more sense for that class to have a non-abstract method that would set it :
public void setMaxSpeed(int maxSpeed)
{
this.maxSpeed = maxSpeed;
}
The sub-classes (such as Turtle) may override this method to add logic, but they should call the base class to set the value.
#Override
public void setMaxSpeed(int maxSpeed)
{
if (maxSpeed > 5)
throw new SomeException();
super.setMaxSpeed(maxSpeed);
}
If setMaxSpeed() stays abstract, it would make more sense for each sub-class that implements this method to have its own maxSpeed member.

In order to access maxSpeed attribute from subclasses, you could:
Declare it as protected (your professor doesn't seem to like this very much, but I think he's lacking a suitable explanation)
Declare a getMaxSpeed() method in the superclass: if knowing the max speed from outside the hierarchy is needed, declare it as public; otherwise, declare it as protected, so that subclasses (specific animals, such as your Turtle) can know what their max speed is.
I agree with #Eran in that the setMaxSpeed() method shouldn't be declared as abstract in the Animal superclass, and subclasses could call super.setMaxSpeed() from their own setMaxSpeed method if they need to do specific processing when their max speed is being set.
Regarding why using protected is claimed to be 'avoided at all costs', or dangerous, etc, please refer to this amazing newsletter's article. My personal opinion is that it is wrong to make such claims, or at least, an overreaction. However, as explained in the article:
We should try to only call either private or final methods from inside our constructors. The reason is that Java always calls the most derived method, which means we could call a method on a half-initialized object.
This means that if you call a protected method from within the constructor of your superclass, and that if the protected method is overriden in one of the subclasses, then the code within that method would run before the rest of the class was fully initialized, which might lead to nasty errors:
class Animal {
protected int maxSpeed;
protected SomeClass someClass;
protected Animal(int maxSpeed, SomeClass someClass) {
this.setMaxSpeed(maxSpeed); // call to subclass method
this.someClass = someClass;
}
public abstract void setMaxSpeed(int maxSpeed); // could also be protected
}
class Turtle extends Animal {
#Override
public void setMaxSpeed(int maxSpeed) {
if (this.someClass.checkIfMaxSpeedMustBeDoubled()) { // throws NPE
this.maxSpeed = maxSpeed * 2;
} else {
this.maxSpeed = maxSpeed;
}
}
}
In this very simple example, this.someClass.checkIfMaxSpeedMustBeDoubled() throws a NullPointerException because this.someClass has not been yet initialized in the Animal superclass. This kind of error is very common when using protected members, but claiming that protected should be avoided is ridiculous. Just be careful and only call either private or final methods from within the superclass' constructor, and you'll be OK.

It is depends on requirement, If you want maxSpeed variable should be present in your all subclasses then put that variable in super class and then reuse that variable in subclass. for that you have to initialize that variable through subclass constructor and change modifier to protected for that variable.
But its better to create variable in your subclass if those are related to your subclass only,

Related

Setting value to abstract private field from subclass

I would like to know about the most efficient way to set a value to an abstract private field from a subclass. So, for example, have a field called itemCost, then I would like to initialize its value to 200 in the subclass.
There is no such abstract private field in Java. Only classes and methods can be abstract. But to emulate an abstract field, I believe there are at least two good methods:
Method (1): Define an uninitialized final field in the superclass. And initialize it in the child class. This is more suitable to constant (primitive) variables and having the variable initialized in the constructor is perfectly fine. It will also work well with complex types of course (class instances with mutable content, instead of primitive types).
Method (2): Define an abstract setter for the field to force the subclass to implement/redefine this method and do the specific initializations. This is more suitable for varying field content but there is no guarantee that the field will be correctly initialized by all subclasses. This becomes implementation-dependent.
Method (1)
abstract class MySuperClass {
final int itemCost;
protected MySuperClass(int _itemCost) {
this.itemCost = _itemCost;
}
}
class MySubClass extends MySuperClass {
public MySubClass() {
super(200);
}
public MySubClass(int itemCost) {
super(itemCost);
}
}
If you do not call super(itemCost) you will get a compiler error. So this is very enforcing.
Method (2)
abstract class MySuperClass {
int itemCost;
protected MySuperClass() { }
abstract void setItemCost();
abstract void setItemCost(int _itemCost);
}
class MySubClass extends MySuperClass {
public MySubClass() {
setItemCost();
}
public MySubClass(int itemCost) {
setItemCost(itemCost);
}
#Override
final void setItemCost() {
this.itemCost = 200;
}
#Override
final void setItemCost(int _itemCost) {
this.itemCost = _itemCost;
}
}
If you are interested in modifying the value after instantiation and if the child class is correctly implemented, then it is a fine solution. But it is a more verbose, less intuitive and error-prone solution.

Best Practices for Implementing Setters/Getters in Subclasses?

If I have a superclass that must retain some functionality, thus requiring setters/getters (I realize this isn't ideal, but that's beside the point), when I implement a subclass, should I include a call to the superclass' setters/getters in the subclass even though I can technically invoke them without writing the code again?
I've posted an example of what I mean below.
class Parent {
private int x;
public void myMethod() {
// Code here.
}
public void setX(int y) {
x = y;
}
public int getX() {
return x;
}
}
class Child extends Parent {
#Override
public void myMethod() {
super.myMethod();
// Different code here.
}
// Are the inclusions below really necessary?
public void setX(int y) {
super.setX(y);
}
public int getX() {
super.getX();
}
}
The whole point of inheritance is to NOT have to reimplement methods in a subclass if the superclass methods do what you need. You should override only if the subclass method needs to do something different/more.
Overriding methods to only call their super version is what you get by default without overriding!
In other words:
#Override
void foo() { super.foo(); }
results absolutely the same as behavior as ... not overriding that method at all.
So, to the contrary: you should consider making those getters and setters final to prevent subclasses from overriding them! And for the record: when overriding methods, you always want to put the #Override annotation on those methods (so the compiler can tell you when you only think you are overriding a method).
should I include a call to the superclass' setters/getters in the subclass
Firstly, if you want the child to have access to private int x, change private to protected.
The only reason I can think of when to return/set different data is when, for example, the subclass does some additional calculations upon y before setting x. Otherwise, if you just delegate to the super method, then that definition is unnecessary.
Use superclass accessors if you need to access private fields from parent objects specifically. If you have different instance fields defined in the child class, you'd need separate getters to access those fields/variables.
Otherwise, just use the predefined super methods, which are inherited by all classes that extend the parent class.

Access a private variable from the superclass (JAVA)

Ok so I have studied java all semester and thought I had a clear understanding about inheritance and super/sub classes. Today we were given as assignment for making a superclass called enemy, with sub classes of different types of enemies. I did everything fine and all of my subclasses are working, but when I went back to read the guidelines we must follow, I found this sentence:
"All member variables of the super class must be private. Any access to a variable must be done through protected methods in the subclasses."
From what I have learned, this makes no sense to me. If a variable is private within the superclass, doesn't that disallow access even from a subclass? The last part that talks about protected methods in the subclasses also doesn't make any sense to me. How does this help and/or allow any access whatsoever to the super class?
From what I've learned about inheritance, Below is what i thought was true:
Access Levels
Modifier 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
If I'm understanding something wrong here please do explain! I don't want to confront the instructor about giving us faulty instructions, if I'm the one not understanding it correctly!
The part
Any access to an a variable must be done through protected methods in the sub classes.
... just means that the subclasses have to call protected methods that are defined in the superclass. Since these methods are protected they can be accessed by the subclasses.
First you would define a base class like this:
public class Base {
private int x; // field is private
protected int getX() { // define getter
return x;
}
protected void setX(int x) { // define setter
this.x = x;
}
}
Then you would use it in your child class like this:
class Child extends Base{
void foo() {
int x = getX(); // we can access the method since it is protected.
setX(42); // this works too.
}
}
Probably the sentence is not worded correctly, from what I understand it makes perfect sense to me :
1. the superclass has private fields and protected methods to access them
2. the subclasses access the fields by using that methods.
Those are just the constraints of the assignment, not Java itself. You could give the superclass protected data members, and then access those directly from the subclass. However, the professor likely wishes to teach you about how a superclass can protect its data members from direct access by a subclass, and protected methods would be a way to do that.
When you inheritance other class, you cannot access your private attributes directly. So, if you have a class named "A" and other called "B", and make B extends A, B cannot access private attributes of A.
Think this like a protection. This way, you can write some attributes in class "A" that you dont want others classes access it through inheritance.
The "B" class can access only public, protected and default attributes directly in "A" class. But if you want to access a private attribute in "A" class for any reasons, you can write a method in "A" to return this attribute.
public class A{
private int foo;
public int getFoo(){
return this.foo;
}
}
public class B extends A{
public void doSomething(){
getFoo(); //return the private foo attribute of superclass
}
}
You are right in your thinking that, literally speaking, you can't access a superclass's private field. The text of your assignment uses wording which is not 100% strict, but is 100% customary in Java parlance: the so-called "getter" methods, also called "accessor" methods, are seen as "accessing the field", even though, strictly speaking, they merely return the current value of the field—which is definitely not the same as giving access to the field itself. You just need to get used to this (and many more) conventions in the Java jargon.
package com.action.product;
public class ProductAction{
public static String strCategoryName;
public String getStrCategoryName() {
return strCategoryName;
}
public void setStrCategoryName(String strCategoryName) {
this.strCategoryName = strCategoryName;
}
}
-----------------------------------------------------------------------
package com.DAO.product;
public class ProductDAO extends ProductAction {
#SuppressWarnings("static-access")
public String addnewProductValidation(){
System.out.println("======through_name======="+super.strCategoryName);
System.out.println("======through_getters======="+super.getStrCategoryName());
}
}
Can initialize variables as static. No need to create object

Private members are not inherited (or overridable) by subclasses in Java?

Isn't that subclass inherits everything from superclass true? But subclass could not access its superclass's private attribute/method, but can access its own. So I wrote a test program. But it seems subclass has not one!
class a {
private void set() {
System.out.println("a.set()");
}
}
public class b extends a {
// private void set() {
// System.out.pritln("b.set()");
// }
void f() {
set();
}
public static void main(String[] args) {
b b = new b();
b.f();
}
}
If I comment out the set() method in b as the example does, it won't compile.
Any idea? Any explanation from JVM view ?
Yes, private methods aren't accessible from a derived class. protected and public are.
When you declare set in your derived class, you gain access to this derived version since it's now part of the class (no longer a private base class method).
You'd still get an error if you attempted to call super.set().
Edit: the trick aroth's talking about I assume is reflection. :) Don't.
The question is meaningless. Private is private. Invisible to everything outside the current class. If you want 'protected', use it.
If you want something in between, use the "protected" modifier instead of the "private" modifier; protected essentially means private to everything but subclasses.

How to create an "abstract field"?

I know abstract fields do not exist in java. I also read this question but the solutions proposed won't solve my problem. Maybe there is no solution, but it's worth asking :)
Problem
I have an abstract class that does an operation in the constructor depending on the value of one of its fields.
The problem is that the value of this field will change depending on the subclass.
How can I do so that the operation is done on the value of the field redefined by the subclass ?
If I just "override" the field in the subclass the operation is done on the value of the field in the abstract class.
I'm open to any solution that would ensure that the operation will be done during the instantiation of the subclass (ie putting the operation in a method called by each subclass in the constructor is not a valid solution, because someone might extend the abstract class and forget to call the method).
Also, I don't want to give the value of the field as an argument of the constructor.
Is there any solution to do that, or should I just change my design ?
Edit:
My subclasses are actually some tools used by my main program, so the constructor has to be public and take exactly the arguments with which they will be called:
tools[0]=new Hand(this);
tools[1]=new Pencil(this);
tools[2]=new AddObject(this);
(the subclasses are Hand, Pencil and AddObject that all extend the abstract class Tool)
That's why I don't want to change the constructor.
The solution I'm about to use is to slightly change the above code to:
tools[0]=new Hand(this);
tools[0].init();
tools[1]=new Pencil(this);
tools[1].init();
tools[2]=new AddObject(this);
tools[2].init();
and use an abstract getter to acces the field.
How about abstract getter/setter for field?
abstract class AbstractSuper {
public AbstractSuper() {
if (getFldName().equals("abc")) {
//....
}
}
abstract public void setFldName();
abstract public String getFldName();
}
class Sub extends AbstractSuper {
#Override
public void setFldName() {
///....
}
#Override
public String getFldName() {
return "def";
}
}
Also, I don't want to give the value
of the field as an argument of the
constructor.
Why not? It's the perfect solution. Make the constructor protected and offer no default constructor, and subclass implementers are forced to supply a value in their constructors - which can be public and pass a constant value to the superclass, making the parameter invisible to users of the subclasses.
public abstract class Tool{
protected int id;
protected Main main;
protected Tool(int id, Main main)
{
this.id = id;
this.main = main;
}
}
public class Pencil{
public static final int PENCIL_ID = 2;
public Pencil(Main main)
{
super(PENCIL_ID, main);
}
}
How about using the Template pattern?
public abstract class Template {
private String field;
public void Template() {
field = init();
}
abstract String init();
}
In this way, you force all subclasses to implement the init() method, which, since it being called by the constructor, will assign the field for you.
You can't do this in the constructor since the super class is going to be initialized before anything in the subclass. So accessing values that are specific to your subclass will fail in your super constructor.
Consider using a factory method to create your object. For instance:
private MyClass() { super() }
private void init() {
// do something with the field
}
public static MyClass create() {
MyClass result = new MyClass();
result.init();
return result;
}
You have an issue in this particular sample where MyClass can't be subclassed, but you could make the constructor protected. Make sure your base class has a public / protected constructor also for this code. It's just meant to illustrate you probably need two step initialization for what you want to do.
Another potential solution you could use is using a Factory class that creates all variants of this abstract class and you could pass the field into the constructor. Your Factory would be the only one that knows about the field and users of the Factory could be oblivious to it.
EDIT: Even without the factory, you could make your abstract base class require the field in the the constructor so all subclasses have to pass in a value to it when instantiated.
Also, I don't want to give the value of the field as an argument of the constructor.
Is there any solution to do that, or should I just change my design ?
Yes, I think you should change your design so that the subclass passes the value to the constructor. Since the subclass portion of your object isn't initialized until after the superclass constructor has returned, there's really no other clean way of doing it. Sure, this'd work:
class Super {
protected abstract int abstractField();
protected Super() { System.out.println("Abstract field: " + abstractField); }
}
class Sub {
protected int abstractField(){ return 1337; }
}
... since the implementation of abstractField() doesn't operate on object state. However, you can't guarantee that subclasses won't think it's a great idea to be a little more dynamic, and let abstractField() returns a non-constant value:
class Sub2 {
private int value = 5;
protected int abstractField(){ return value; }
public void setValue(int v){ value = v; }
}
class Sub3 {
private final int value;
public Sub3(int v){ value = v; }
protected int abstractField(){ return value; }
}
This does not do what you'd expect it to, since the initializers and constructors of subclasses run after those of the superclass. Both new Sub2() and new Sub3(42) would print Abstract field: 0 since the value fields haven't been initialized when abstractField() is called.
Passing the value to the constructor also has the added benefit that the field you store the value in can be final.
If the value is determined by the type of subclass, why do you need a field at all? You can have a simple abstract method which is implemented to return a different value for each subclass.
I think you need a factory (aka "virtual constructor") that can act on that parameter.
If it's hard to do in a given language, you're probably thinking about it incorrectly.
If I understand you correctly: You want the abstract class's constructor to do something depending on a field in the abstract class but which is set (hopefully) by the subclass?
If I got this wrong you can stop reading ...
But if I got it right then you are trying to do something that is impossible. The fields of a class are instantiated in lexical order (and so if you declare fields "below", or "after", the constructor then those will not be instantiated before the constructor is called). Additionally, the JVM runs through the entire superclass before doing anything with the subclass (which is why the "super()" call in a subclass's constructor needs to be the first instruction in the constructor ... because this is merely "advice" to the JVM on how to run the superclass's constructor).
So a subclass starts to instantiate only after the superclass has been fully instantiated (and the superclass's is constructor has returned).
And this is why you can't have abstract fields: An abstract field would not exist in the abstract class (but only in the subclass) and so is seriously(!) "off limits" to the super (abstract) class ... because the JVM can't bind anything references to the field (cause it doesn't exist).
Hope this helps.

Categories

Resources