Reputation: 23
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.
Upvotes: 2
Views: 1060
Reputation: 10084
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.
Upvotes: 0
Reputation:
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;
}
}
Upvotes: 1
Reputation: 3346
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.
Upvotes: 2
Reputation: 129497
(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");
}
}
Upvotes: 0
Reputation: 16365
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;
}
}
Upvotes: 1