How to access private fields from parent class - java

I am testing out various combinations to build a super class and a subclass and I realized there is no way to access the private fields from the parent class when I do the following:
abstract class Ball{
private int size;
protected Ball(int size){
this.size = size;
}
public abstract void setSize(int size);
public abstract int getSize();
}
class SoccerBall extends Ball
{
public SoccerBall(int size){
super(size);
}
#Override
public void setSize(int size){this.size = size;}//size not inherited
#Override
public int getSize(){return size;} //size not inherited
}
I know private fields won't be inherited to the subclass. The only way (probably the only way other than reflection) to access it is to use getter and setter.
So my questions:
(Q1) If I want to keep the field in the parent class as private and not protected. Should I not make the getter and setter abstract in order to make the private field accessible to its child?
(Q2) If I were to make the field (size) private, how should I implement my getter and setter to make the private field accessible by the subclasses?

Instead of trying to access the value directly, change the access level of size to "protected". This way, it will will be mostly encapsulated except when accessed by subclasses.

If I want to keep the field in the parent class as private and not protected. Should I not make the getter and setter abstract in order to make the private field accessible to its child?
Yes, since the field is private and can only be accessed if a getter and setter is defined in the parent class. The getter and setter should not be declared as abstract.
If I were to make the field (size) private, how should I implement my getter and setter to make the private field accessible by the subclasses?
Just implement a normal getter and setter in the parent class where the private field resides.
abstract class Ball{
private int size;
protected Ball(int size){
this.size = size;
}
protected void setSize(int size){
this.size = size;
}
protected int getSize(){
return size;
}
}
The subclass
class SoccerBall extends Ball{
public SoccerBall(int size){
super(size);
}
#Override
public void setSize(int size){
super.setSize(size);
}
#Override
public int getSize(){
return super.getSize();
}
}

Related

Attribute should not be changed after creation

Given the question - "All game objects provide the ability for external code to obtain their size. However, they do not provide the ability to have their size changed once it is created."
If I have a parent class with private fields such as this GameObject class:
public abstract class GameObject {
private int size;
public void setSize(int size) {
this.size = size;
}
}
and a children classes such as
public class Dinosaur extends GameObject {
public Dinosaur() {
this.setSize(100);
}
}
public class Jeep extends GameObject {
public Jeep() {
this.setSize(10);
}
}
How do I ensure that the size is not changed after the object is created?
I am confused because if I make the setter method for size private then I cannot set the size for each GameObject individually upon creation.
EDIT: Added second child class for clarity.
If you need to make the size variable unchangeable then you should use final modifier.
There are 2 ways to set the value for this kind of variables: 1) constructor 2) inline. As long as you would like to have an option to set your custom value in the client code for each object, you should use constructor:
public abstract class GameObject {
private final int size;
public GameObject(int size) {
this.size = size;
}
}
public Dinosaur extends GameObject {
pubilc Dinosaur(int size){
super(size);
}
}
There is no need in setter method in that case.
size can be final and size value passed in the constructor. Also you do not need a setter. You can make only the necessary getter.
public abstract class GameObject {
private final int size;
public GameObject(int size) {
this.size = size;
}
public int getSize() {
return this.size;
}
}
They're a few things wrong with your code.
First if the class shouldn't have the ability to set the size after creation, why provide a setter in the first place?
Second, a subclass could override your setSize method in the abstract class and do whatever it wanted. If you want inheritance do this:
public abstract class GameObject {
private final size;
public GameObject(int size){
this.size = size;
}
}
public class Dinosaur extends GameObject {
public Dinosaur(int size){
super(size)
}
}
No setter is provided and the size must be made available at construction time. If you want a method to do it, make the method final. Like this:
public final setSize(int size){
this.size = size;
}
By making it final the subclasses have to except the method as it is, no overriding.
Another approach is, make this class immutable. You don't use setters, but you can have getters, and the class would be made final, so no subclassing.
public final Dinosaur {
private final int size;
pubilc Dinosaur(int size){
this.size = size;
}
public int getSize(){
return this.size;
}
}
(Note: I'm assuming you meant to have Dinosaur extend GameObject.)
You could override the setSize() method and throw an exception:
public class Dinosaur extends GameObject {
...
#Override
public void setSize(int size) {
throw new UnsupportedOperationException("can't change dinosaur size");
}
}
Given the question - "All game objects provide the ability for
external code to obtain their size. However, they do not provide the
ability to have their size changed once it is created."
The usual way that this is done is by having the constructor of the parent class accept a size argument. This argument sets the value of an immutable size field. Subclasses may easily access this value, but they are unable to change it once it has been set. This is the most object-oriented way in which to meet the listed requirements.
For example:
public abstract class GameObject {
private final int size;
public GameObject(int size) {
this.size = size;
}
public int size() { return this.size; }
:
:
}
and a child class:
public class Dinosaur extends GameObject {
public Dinosaur() {
super(100);
}
:
:
}
Although there is some discussion in this thread about how subclasses may dynamically change the size field, a better design would be to use an immutable design like the one presented here and have client code request a new object with a different size if needed (say, with a copyOf() method). Immutable designs have several advantages over mutable ones and are usually the way to go when planning value classes.

Abstract Classes in Java and their object variables

i am wondering what happens with object variables in abstract classes in Java. For example if have this abstract class:
public abstract class BaseClass{
private int[] myNumbers;
public Baseclass(int length){
myNumbers = new int[length];
}
public boolean isOne(int index){
return myNumbers[index] == 1;
}
}
and i have this real class which extends the BaseClass:
public class ArrayClass extends BaseClass{
private int[] myNumbers; //i have to define it again?
public ArrayClass(int length){
super(length); //does this affect my array? I don't think so
}
public void setValue(int index, int value){
if(!isOne(index))
myNumbers[index] = value;
}
}
I want to define basic operations in my BaseClass and do some other stuff in my normal ArrayClass. Because i need an array in my BaseClass i have to define one to work with it in the different methods (obviously).
But in my ArrayClass which extends BaseClass i have to define another array. I am not sure why this is and if it needs to be this way? I hope you understand what i mean. For example i could utilize the BaseClass a second time for this normal class:
public class ArrayClass2 extends BaseClass{
private int[] myNumbers;
public ArrayClass2(int length){
super(length);
}
public int getValue(int index){
if(!isOne(index))
return myNumbers[index];
else
return 1;
}
}
The myNumbers array needs to be protected, not private in order to be accessible from within a sub class.
Read more: https://www.tutorialspoint.com/java/java_access_modifiers.htm
Java has four access types. You can read about them here.
If you want to expose the field in your base class to its children, you can use protected modifier.

How to set fields in an abstract class?

I have an abstract class with a field in it, which should have following properties:
readonly for the public interface
writeonly for the subclasses
My question now is: how should I set and initialize this field?
public abstract class A {
// initialize it here ?
private int field = 0;
// initialize it in constructor ?
protected A(int field)
{
this.field = field;
}
// use protected setter ?
protected void setField(int val){
this.field = val;
}
// or use protected field
protected int field;
public int getField(){
return field;
}
}
How to initialize/access this field?
public class B extends A {
public B(int val){
super(val);
// or
setField(val);
// or
field = val;
}
}
and is it a good idea to use something like a protected constructor?
It's basically on your need
If you want to initialize super class field at the creation of child object it self, then you could call super(val);
If you want to create your child object independent of parent object's field values. use Default contructor for child class and if required to set parent value call setField(val); method on child object.
is it a good idea to use smth. like a protected constructor ?
Yes if you really want to restrict access for the classes within the package

Inheriting java constructors

I have a super class 'BuildingMaterial' and loads of subclasses, i.e. Stone, Wood, Clay, etc.
All subclasses behave similarly: 1 int field that stores the amount of a building material in units. They can be constructed parameterless or with an int. I already know that ALL subclasses of BuildingMaterial will have these two constructors, how do I avoid coding them into every single class?
Here's an example of what I don't want to do in every class:
public final class Stone extends BuildingMaterial {
private int amount;
//constructors
public Stone() {
amount = 0;
}
public Stone(int i) {
amount = i;
}
//methods
public int getAmount() {
return amount;
}
}
Sadly, the answer is you can't. This is a limitation of the Java language. Each class needs its own constructors—you can't simply inherit them from a parent class. The only constructor the Java compiler will generate for you is the default constructor (no arguments), and it only generates that if you don't specify any constructors at all.
The best you can do here is to refactor your code so amount is in the superclass:
public abstract class BuildingMaterial {
private int amount;
//constructors
public BuildingMaterial() {
this(0);
}
public BuildingMaterial(int i) {
amount = i;
}
//methods
public int getAmount() {
return amount;
}
}
And then make use of super calls to delegate the superclass's constructor in your subclasses:
public final class Stone extends BuildingMaterial {
//constructors
public Stone() {
super();
}
public Stone(int i) {
super(i);
}
}
Note that I changed the body of your no-argument constructor from amount=0; to this(0);. I personally think this is better style because, if you decide to add other initialization code to your constructor body, you only have to add it to the 1-argument constructor, and the zero-argument constructor will just delegate all the work to it.
You have to use inheritance
public abstract class BuildingMaterial {
private int amount;
//constructors
public BuildingMaterial() {
amount = 0;
}
public BuildingMaterial(int i) {
amount = i;
}
//methods
public int getAmount() {
return amount;
}
}
public class Stone extends BuildingMaterial {
public Stone() {
super();
}
public Stone(int i) {
super(i);
}
}
This way all subclasses of BuildingMaterial can give access to amount through getters and setters.
You may have amount declared as protected so you wont need getters or setters to access that field inside subclasses.
use super keyword to reduce your code but the super is to be the first line inside the constructor
public class Stone extends BuildingMaterial {
public Stone() {
super();
}
public Stone(int i) {
super(i);
}
}
If all classes has the attribute amount, then that attribute can be inherited from parent. Define amount in your parent class BuildingMaterial and then call the parent constructor from your child classes constructors using super to set the amount value.
Its unclear what you want to avoid in your question... assuming you are talking about avoiding writing multiple constructors in all the subclass. I believe its not possible to do so. below post of defining BuildingMeterial constructor and calling the super() from baseClass will be the best solution to use.

Static parameter with different values in subclasses

I want to create a solution for the following problem without much redundancy:
I have an abstract class Unit, subclasses SubUnit1 and SubUnit2. All Units have a maxValue, which differs from SubUnit1 to SubUnit2, but should be the same for all instances of the same sub unit at any time.
I don't want to copy all the setters, getters or some kind of method around these values, because they are identical for all subclasses. I also don't want to use normal paramters and hand down the methods to subclasses and update every single instance of these subclasses if necessary. And somehow get the current value when I create a new instance.
Is there a way to declare some sort of static parameter and methods in the parent class Unit, that differ in the different subclasses?
You could define a protected constructor in the parent class that accepts the value of the MAXVALUE
public abstract class Unit {
private final int maximum;
protected Unit(int maximum) {
this.maximum = maximum;
}
public int getMaximum() {
return maximum;
}
}
Then in your derived classes you expose constructors that call the parent's constructor with a fixed value, unique per subclass.
public class SubUnit1 {
private static final int SUBUNIT1_MAX = 10;
public SubUnit1() {
super(SUBUNIT1_MAX);
}
}
No, but using an interface you may express that a UNIT should have a MAXVALUE.
public interface IUnit
{
public int getMaxValue();
}
public class SubUnit implements IUnit
{
private static final int MAX_VALUE = 48;
#Override
public int getMaxValue() {
return MAX_VALUE;
}
}

Categories

Resources