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.
Related
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.
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();
}
}
I have a base class
public class base
{
//some stuff
}
and several subclasses
public class sub1 extends base
{
static int variable;
}
public class sub2 extends base
{
static int variable;
}
etc
The static int variable exists in every subclass because I store in it information that is characteristic for every subclass. But it would be better if there was a way to move static int variable to base class in the way that it still will be different for every subclass.
In the way that it is now I am repeating myself, when adding some another subclass, it's a bad practice.
So anyone has some idea how to acomplish this? Maybe there's a design pattern that fits to this situation?
You cannot move all the different static variables from derived classes into the base class, because static variables are one-per-class; you want your variables to be one-per-subclass, which is not allowed.
You could work around this issue by defining a registry of subclasses in your base class, and store the int for each subclass there. However, this would add a lot more complexity, and it is not clear how you would differentiate between subclasses in the superclass.
Your current solution appears optimal.
Don't use a static field for this - that's not the way to go, because static fields of a subclass do not "override" those of a super class.
Instead, because the values are constant for a given class, use a final instance field:
public class Base {
protected final int variable;
public Base() {
this(5);
}
protected Base(int v) {
variable = v;
}
}
public class Sub1 extends Base {
private static int v = 7;
public Sub1() {
super(v);
}
}
Now the variable is fixed and accessible to all instances.
You can certainly move variable into the base class, but it cannot be static. Alternatively, you can make static getters which you override in each subclass. Here is an example of both:
public class base {
protected int variable;
protected static int getVariable() {
return -1;
}
}
public class Sub1 extends base {
public Base() {
variable = 0;
}
protected static int getVariable() {
return 0;
}
}
public class Sub2 extends base {
public Sub2() {
variable = 1;
}
protected static int getVariable() {
return 1;
}
}
As a design principle, it is somewhat rare (in my opinion) that you genuinely want static methods. Usually you will have some instance of the class around that you are working with. If you want a whole bunch of objects to share some common behavior which you configure at runtime, you might want to check out the flyweight pattern.
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.
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;
}
}