I have the following:
Public Abstract class Entity
protected int damagePoints = 0;
public getDamagePoints() {
return this.damagePoints;
}
Public abstract class IA extends Entity
Public class Zombie extends IA implements Attacker {
protected int damagePoints = 40;
}
Public class Engineer extends Entity implements DamageReceiver;
Public interface Attacker {
public attack(Entity entity);
}
Public interface DamageReceiver {
public receiveDamage(Attacker entity)
}
The Engineer class has this method overriden:
#Override
public void receiveDamage(Attacker entity) {
if (entity instanceof Zombie) {
int damagePoints = ((Zombie) entity).getDamagePoints();
this.setHealthPoints(this.getHealthPoints() - damagePoints);
}
}
Now I have an Engineer instantiated, and a Zombie.
When I do Zombie.attack(engineer), and I put a breakpoint in receiveDamage() in Engineer class, I get that damagePoints is 0.
Any clue of why this happens? Is this because I duplicated the property damagePoints? If so, how can I have a Zombie to have 40 of damage points without repeating the this.damagePoints = 40 in all constructors?
You re-declared damagePoints in Zombie, hoping that getDamagePoints() in Entity would pick up the new value in Zombie, but as you've seen, it didn't. In Java, polymorphism works with method calls, but not with variables. The damagePoints variable in Entity is the variable in scope for the getDamagePoints() method, so 0 is returned, from Entity's damagePoints variable.
To get 40 returned in Zombie, you don't need to re-declare another variable of the same name, hiding the damagePoints variable in Entity, but you can override the getDamagePoints() method in Zombie. You don't need a variable for that, much less a variable of the same name (unless you plan on having that quantity change during the game). In Zombie:
#Override
public int getDamagePoints() {
return 40;
}
You may even want your getDamagePoints() method to be abstract in Entity, forcing subclasses to implement the method. This would mean that the variable damagePoints would be unnecessary in Entity.
public abstract int getDamagePoints();
This is happening because when you call getDamagePoints, it's returning the abstract class Entity's damagePoints value, not the class that has extended it. Fix this by making Entity's getDamagePoints method abstract, and provide an implementation for every extended class.
It appears Zombie has multiple constructors, all of which need to initialize damagePoints to avoid repeated code, including possibly repeating the method getDamagePoints.
The solution is to use "this" to tie constructors together. For example, if one constructor takes a superset of the parameters for each of the other constructors, do the actual work in it:
public Zombie(/* some subset of parameters */){
this(/* full set of parameters with defaults filled in */);
}
public Zombie(/* full set of parameters */){
damagePoints = 40;
/* rest of initialization */
}
If there is no common superset constructor, you can still use "this" to do the common work. You may need to use a special private constructor:
private Zombie(boolean special) {
damagePoints = 40;
}
public Zombie() {
this(true);
/* Rest of the constructor */
}
Related
I have an abstract class like this:
public abstract class Block {
private boolean collided = false;
public boolean hasCollided() {
return collided;
}
public void markCollided() {
collided = true;
}
}
I have 4 sub classes for the Block class. Those class also require to receive the collided variable. That means the two methods should be overridden by the 4 sub classes of Block. How can I make it work?
If I try to override it, it will show error because sub classes does not contain such a variable in it.
How can I receive the collided variable in all sub classes?
Also,I created an array of block class that array contains 4 subclass objects.Is it possible to set different values for the collided variable for each object,while traversing the array?
In short,the colllided variable can be unique for each object in the array?
You need to use the public methods hasCollided(), markCollided() etc., because collided is a private variables for class Block .
The fact the 4 sub classes extends Block ,that doesn't mean can access private fields. Block provided public hasCollided,markCollided to access its private variables.
You cannot access the collided variable directly because it is private. But
you can use the hasCollided() method of the superclass to return the parent class' collided variable.
public class subBlock {
public boolean hasCollided() {
return super.hasCollided();
}
public void markCollided() {
super.hasCollided()= true;
}
}
Say I have like 50 different classes that extends "CustomEnchantment", is there any way to have a static getter in the abstract class that gets me one of the values of a specific class. Say I want max level of "Rage" then i'd do Rage.getMaxLevel() or something, in a static way. Problem is that getting an instance would mean i'd have to make 50+ instances 1 for each enchant. I want to just have a fix way to get a specific enchant's max level. I have tried to just include a "getMaxLevel()" and it returns it fine, but with that, i would need an instance of every single class that extends the abstract class, i'd rather have a static way of getting 1 specific class value.
Some examples:
I have 3 classes extending Person. Person includes the variables age and name.
In the class Josh, his name is set to "Josh" and age 17. In the class Jeff, his name is "Jeff" and age 20. In the class Jennica, name is "Jennica" and her age is 19. What I need is a method to return the age from a specific one of these classes at any time with only 1 method. So for example (This wont work) getAge(Jennica) gets Jennica's age, getAge(Josh) returns 17 for his age etc.. I need this to be used in a static or in a way where I can access it easily.
By a static variable, you could realize that. You just have to take care that your static member is always updated by the subclasses max-level. If your code grows, that will make it unmaintainable.
A better approach could be to make an Manager-class like "CustomEchantmentManager" or something else. It could store a list of all your instances. Also, it could store an attribute like CustomEchantment enchantmentWithHighestLevel, where you store the instance with the highest level. Let your manager observe the enchantments and after a new level of one enchantment, check if it's level is higher than the actual stored enchantment's level and if yes, overwrite it's reference in the attribute. This will not change all your instances because it just references to your instance with the highest level.
Example for the manager:
public class CustomEnchantmentManager implements Observer {
private ArrayList<CustomEnchantment> enchantments;
private CustomEnchantment enchantmentWithHighestLevel = null;
public CustomEnchantmentManager() {
enchantments = new ArrayList<CustomEnchantment>();
}
#Override
public void update(Observable obs, Object o) {
if(this.enchantmentWithHighestLevel.getLevel() > ((CustomEnchantment)o).getLevel) {
//do Nothing
else {
this.enchantmentWithHighestLevel = (CustomEnchantment)o;
}
}
Example for an enchantment:
public class CustomEnchantment() extends Observable {
public int level = 0;
public CustomEnchantment() {
}
public void incrementLevel() {
this.level++;
setChanged(); //method from Observable
notifyObservers(this); //send Observers instance of this object
}
}
So as part of a car rental system I need to write classes to represent large and small cars, the difference between these being that they have different size tanks and consume fuel at different rates. Currently my approach is to have an interface, Car, implemented by an abstract class AbstractCar, which is extended by two concrete classes SmallCar and LargeCar. However this is my first time using interfaces and abstract classes (we are just covering them in class and this assignment is designed to assess our knowledge of them) and I'm having trouble knowing what to place in what class.
The fill method implementations are exactly the same, they just need to refer to the correct value of FUEL_CAPACITY, so it feels that I should be implementing these methods in the AbstractCar class, but then I don't know how to get them to refer to the correct FUEL_CAPACITY values. The field fuelLevel is also obviously held by all cars so it feels that I should declare it in AbstractCar, but then I cannot access it from the subclasses without removing its privacy.
Would anyone be able to help me figure out what I'm doing wrong or misunderstanding about interfaces and inheritance? One thing I've been considering is producing an enum CarType, having AbstractCar hold a CarType as a field and all implementation is done in the AbstractCar class using if statements to switch to the correct FUEL_CAPACITY value, and simply using SmallCar and LargeCar as constructors or factory classes without much or even any actual implementations.
Thanks in advance for any help I realise its a bit long winded, however I try to make sure I'm fully understanding the concepts we are learning and that I'm implementing them correctly rather than just botching together something that 'works' but might not necessarily be the correct or most elegant solution.
You can transfer the logic to the AbstractCar with the values like you pointed out. Then just set those values in the constructor of SmallCar and LargeCar. This would be one approach. Like you pointed out, you always have to have the common logic in the parent class. You want to avoid duplicate code. Then you just have to make sure you set different values in the constructor. And if you know the fix value (as you do from the given example), you can even omit giving parameters to SmallCar or LargeCar constructors and just set those fixed values in the super() call inside the constructor.
Here is the implementation of my solution.
The interface Car, where I REMOVED the getFuelMethod() method since the access level has to be protected:
public interface Car {
RegistrationNumber getRegistration();
int getFuelCapacity();
// int getFuelLevel(); this can not be implemented
// all methods in an interface are PUBLIC
// so you have to lower the access level by removing it from the interface
// HERE goes the rest of the method signatures
}
}
The abstract class AbstractCar:
public abstract class AbstractCar implements Car {
// this is the common variable
// that is why we save it in the parent class
private int fuelCapacity;
private int fuelLevel;
// we forward the value to the parent constructor with the super call
public AbstractCar(int fuelCapacity) {
this.fuelCapacity = fuelCapacity;
// I set the value to 0 for the start, but
// you can also pass the value to the super call,
// same as fuelCapacity - it is up to you
this.fuelLevel = 0;
}
// The getters and setter allow us to retrieve the values
// from the abstract class through capsulation!
// here we have the getter to be able to retrieve the value from SmallCar and LargeCar
public int getFuelCapacity() {
return.fuelCapacity;
}
public void setFuelCapacity(int fuelCapacity) {
this.fuelCapacity = fuelCapacity;
}
protected int getFuelLevel() {
return fuelLevel;
}
protected void setFuelLevel(int fuelLevel) {
this.fuelLevel = fuelLevel;
}
// HERE goes the rest of the code
}
Here is the SmallCar implementation:
public class SmallCar extends AbstractCar {
private static final int FUEL_CAPACITY = 45;
public SmallCar() {
// we set the value in the parent class
super(FUEL_CAPACITY);
}
public int drive() {
// HERE goes the logic for drive for SmallCar. Same method is needed
// in the LargeCar class, because the logic differes.
}
// HERE goes the rest of the code
}
If you just want to hide FUEL_CAPACITY from the class user but not from the further developers, you can declare it as protected in the AbstractCar and initiallize it with a proper value in the child classes. Also I would declare a getter method getCapacity() in the AbstractCar which returns this value.
If your Capacity is only one property (only data) of Car, use #Jernej K approach, but if calculating the capacity may have some logic, use this:
Best way is to use abstract methods. you put a method to abstract Integer getCapacity(); in your abstract class
public abstract class AbstractCar implements Car {
private final RegistrationNumber registration;
private boolean isRented;
AbstractCar() {
this.registration = RegistrationNumber.getInstance();
}
public RegistrationNumber getRegistration() {
return registration;
}
public boolean isRented() {
return isRented;
}
//You can use this method in other methods of AbstractCar, but is implemented in your concrete classes
public abstract Integer getCapacity();
public boolean isFull() {
if (fuelLevel == getCapacity()) {
return true;
} else return false;
}
}
and then use it in other functions. and in your concrete class, you define the body of method:
public Integer getCapacity(){
//Your logic to calculate capacity for every concrete class here
}
I do not quite understand the use of "static" properly.
I have a class which includes variables that I want to access from a different class.
However, when I try to access this getter method from the different class I get an error stating:
"non-static method getAccNumber() cannot be referenced from a static context."
So, how can I find this variable's value without making it static. The problem with this is if I make it static, every instance of this object overwrites the previous value.
So they all end up with the same account number in this case.
Let me explain in more detail:
I have a Class called Account, which contains a variable called accountNumber, and a getter method called getAccNumber().
I have a second class called AccountList which is a separate arraylist class to store instances of Account. I want to create a method to remove an element based upon its accountNumber. So I'm searching and using getAccnumber() within the AccountList class to compare with a user parameter and removing if correct!
But I can't use this method without making it static!!
Any help/explanation would be greatly appreciated :)
This is what I am trying to do:
public boolean removeAccount(String AccountNumber)
{
for(int index = 0; index < accounts.size(); index++)
{
if (AccountNumber.equals(Account.getAccNumber()))
{
accounts.remove(index);
return true;
}
}
return false;
}
Thank you!
Let's take an example where you have
public class A {
static void sayHi() { System.out.println("Hi");
//Other stuff
}
and
public class B {
void sayHi() { System.out.println("Hi");
//Other stuff
}
Then
public class C {
public C() {
A.sayHi(); //Possible since function is static : no instantiation is needed.
B.sayHi(); //Impossible : you need to instantiate B class first
}
You can check out this link for a short definition:
Static Method Definition
If you declare a variable as static, it will not be unique for each instance of the class. If you declare the variable as private only, then you can create getter and setter methods that will allow you to access the variable after you have created an instance of the class. For example, if you have classA and classB and you are working in classB and want the private int size of classA:
classA a = new ClassA();
int size = a.getSize(); //getSize() returns the private int size of classA
A static variable is one that lives with the class itself. A non-static variable is unique to each instance of that class (i.e., each object built from that class.) A static variable you can access as a property of the class, like:
SomeclassIMadeUp.numberOfFish;
so if you change the numberOfFish property for that class, anywhere you reference it, you see the change (as you've noticed.)
To have one unique to each instance, don't declare the variable as static and then add a getter and/or setter method to access it.
like
private int numberOfFish;
public int getNumberOfFish() { return (numberOfFish); }
So to your question...
Ocean pacific = new Ocean();
pacific.water = Ocean.salty; // <-- Copying the value from a static variable in the class Ocean
// to the instance variable in the object pacific (which is of Ocean class).
pacific.setNumberOfFish(1000000000);
Octopus o = new Octopus();
o.diningOpportunities = pacific.getNumberOfFish(); // <-- Calls the public method to return a
// value from the instance variable in the object pacific.
Does anybody know if there's a way in Java to set the value of an instance variable in a subclass before calling the superclass constructor. I have a brief schematic below of what I'm trying to accomplish -- I need to set up the instance variables defined in the superclass differently depending on the subclass type, but I still want to be able to share common non-constructor code among different instances of the subclass.
Is there any clean way to do this, maybe some sort of coding pattern that I'm missing or something? Thanks in advance for any ideas.
public abstract class ConstraintSatisfactionProblem {
final Set<Variable> variables;
final Set<Constraint> constraints;
public Foo() {
this.variables = setupVariables();
this.constraints = setupConstraints();
}
public abstract Set<Variable> setupVariables();
public abstract Set<Constraint> setupConstraints();
public Map<Variable, Constraint> solve() { ... }
}
public class WordSquare extends ConstraintSatisfactionProblem {
final int size;
final static Set<Character> domain = ...;
public WordSquare() {
super(); // can I simulate calling super() after setting this.value = 4?
this.value = 4;
}
public Set<Variable> setupVariables() {
this.variables = new HashSet<Variable>();
for(int row = 0; row < size; ++row) {
for(int col = 0; col < size; ++col) {
variables.add(new Variable<Pair, Character>(new Pair(row, col), domain);
}
}
return this.variables;
}
public Set<Constraint> setupConstraints() {
// setup code specific to this problem
}
}
public class Cryptarithmetic extends ConstraintSatisfactionProblem {
final String problem;
public Cryptarithmetic(String problem) {
super();
this.problem = problem;
}
public Set<Variable> setupVariables() {
this.variables = new HashSet<Variable>();
for(char c : problem.toCharArray()) {
variables.add(new Variable<Character, Integer>(c, getDomain());
}
}
return this.variables;
}
public Set<Constraint> setupConstraints() {
// setup code specific to this problem
}
}
Firstly, please don't.
Secondly, really it's a really bad idea. Don't. Think about what you are trying to do in a broader context.
If you absolutely must do, you can stash it in a ThreadLocal. You can call a (non-instance) method by evaluating an expression the result of which is passed to a super() or this() (possibly the only reason why you need a second, private constructor that possibly takes a Void (capital 'V') argument). It's so evil, I am not going to even write the code down.
In your edited example code, just pass the sets into a protected constructor. If you have many arguments possibly some subclasses being special about some arguments, you might want to wrap all the arguments into a single argument object.
There is another really hacky approach, so long as you have -target 1.4 or later (which you should do!). Make the subclass an inner class (possibly anonymous). The references to the outer this and other captured variables are available before calling the super constructor.
public class Outer {
// What a hack!
private static abstract class Base {
Base() {
hello(); // Calling a virtual method in a constructor - poor form.
}
abstract void hello();
}
public static void main(String[] args) {
// Do not do this.
final String hi = "Hi!";
new Base() {
void hello() {
// Really, don't do it.
System.err.println(hi);
}
};
}
}
Place the common code you want to run in a protected method instead of in the constructor. Call that method when you wish.
You should never call any "alien" method (ie. overridable method of this class, or any method from any other class) form within a constructor. As long as the object is not fully initialized, you may have side-effects like the one you see.
In your case, in the subclass constructor, super() is called even before the "value" is set to 4. This means, the superclass constructor is called, then calls the "setup" method, while the "value" is still at 0.
Only once the superclass constructor returns, the "value" is set to 4. And it's too late then.
What I would recommend, is to set the "o1" variable to protected, so that subclasses can set its value themselves.
In Java, if you want to call a base class's constructor, you have to do it on the first line of your sub-class's constructor. So the answer is no, you can't set this.value before calling the super class's constructor.
But your sub-class's setup() method is already called in the super's constructor. Why don't you set your value there?
UPDATE:
Sorry, I didn't pay attention that your 'setup()' method returns a value. What you could do is make an abstract init() method in your super class, and call it in your super constructor before you call the setup() method. This way sub-classes will be forced to implement init(), and you would know that that is the place to initialize any sub-class's members before they are used in your super-class.
That being said, this approach does not force safety on you. When you call the super constructor from your sub-constructor, the sub-class instance is just starting to get created. It still needs to run the rest of the code in the sub-constructor before the object is safely created.
And in this situation, the super-constructor goes and calls the init() method on your just-in-the-process-of-creation sub-class. This means that if you go with approach, you have to be extra careful about what you do in the init() class.
Like others have said, don't do this. If you want to share some code between these classes, try containment/encapsulation instead of inheritance.
public class Foo {
private final Object o1;
public Foo(Object o) {
o1 = o;
}
public void complexMethodCommonToAllSubclassesOfFoo() { ... }
}
public class Bar {
private final int value;
private final Foo foo;
public Bar() {
super();
this.value = 4;
this.foo = new Foo( new Object() ); // or whatever
}
// If you need to expose complexMethodCommonToAllSubclassesOfFoo to clients of this class, just add the method and delegate to foo like this
public void complexMethodCommonToAllSubclassesOfFoo() {
foo.complexMethodCommonToAllSubclassesOfFoo();
}
}
I need to set up the instance variables defined in the superclass differently depending on the subclass type, but I still want to be able to share common non-constructor code among different instances of the subclass.
In that case, create a protected constructor in the superclass, and pass all of the customized values to it when you construct the subclass.