I'm making a game with different types of building. I'm making an interface for each type. Some buildings have more than 1 type.
I have this code:
public interface DefenseBuilding {
int range;
int damage;
public void shoot ();
}
It gives me an error on the 2 variable declarations (range & damage). The error being something along the lines of "Final variable may not be initialised"
It works if I assign the variable in the interface, but I don't want to do that.
I can't just extend a class, because - as said earlier - some buildings need more than 1 type. Classes can only extend 1 other class so I need to use interfaces.
What I'm asking is, is there a way to have variables in an interface without having to initialise the variable inside the interface?
The whole point of interfaces is to specify as interface - i.e. how will your classes interface with client classes. Instance variables are clearly not part of any interface at all.
Instead, try this:
public interface DefenseBuilding {
public void shoot ();
}
and this:
public abstract class AbstractDefenseBuilding implements DefenceBuilding {
protected int range;
protected int damage;
}
edit:
Your classes should now extend AbstractDefenseBuilding, so they will inherit the variables. They also indirectly implement DefenceBuilding so they'll still be forced to implement the shoot() method (unless they are also abstract)
You can use a property method aproach.
public interface DefenseBuilding {
public void setRange(int range);
public int getRange();
public void setDamage(int damage);
public int getDamage();
public void shoot ();
}
Then in your class
public MyClass implements DefenseBuilding{
int range;
int damage;
public int getRange() {
return range;
}
public void setRange(int range) {
this.range = range;
}
public int getDamage() {
return damage;
}
public void setDamage(int damage) {
this.damage = damage;
}
public void shoot (){...}
}
All variables in Interface are static and final. Hence, unless initialized, compiler will keep giving an error that it is not initialized. This is enforced because interface cannot be instantiated and therefore any variable should be of static in nature and cannot be changed.
If your intention is to define class variables, do as NickJ suggested.
Interfaces define behavior but not state (other than constants). Protected variables are a potential danger to proper encapsulation of data (an object should hide its data and provide access through methods unless there is a very compelling reason not to). An alternative would be the following:
public interface DefenseBuilding {
public void shoot();
public int getRange();
public int getDamage();
}
It's also VERY common to provide an abstract class that partially implements the interface:
public abstract class AbstractDefenseBuilding implements DefensBuilding {
private int range;
private int damage;
public AbstractDefenseBuilding(int range, int damage) {
this.range = range;
this.damage = damage;
}
public int getRange() {
return range;
}
public int getDamage() {
return damage;
}
}
Related
When setting a value of a parent class, which way is more preferable:
Set a field
public abstract class Weapon {
final Integer damage;
}
public class Knive extends Weapon {
public Knive(){
damage = 100;
}
}
Override a method
public abstract class Weapon {
public abstract int getDamage();
}
public class Knive extends Weapon {
#Override
public int getDamage(){
return 100;
}
}
Or is it just personal taste?
I think it depend on the situation. Both examples correct.
Your fist approach is more preferably when you have inheritance, and the're general logic for number of child classes. BUT, do make your property protected.
Second approach, is more suitable when you use light classes, like strategies without default implementation. In this case you can change your parent class to interface.
public abstract class Weapon {
protected final Integer damage;
protected Weapon(Integer damage) {
this.damage = damage;
}
// more logic here
}
public class Knive extends Weapon {
public Knive(){
super(100);
}
}
OR
public interface Weapon {
Integer getDamage();
}
public class Knive implements Weapon {
// light-weight strategy
public Integer getDamage() {
return 100;
}
}
The two ways are not opposed. You could use the one, the second or both.
But these don't have the same intention.
A constructor with parameter allows to value the created instance with this parameter : it sets the instance state.
While specifying a method as abstract allows to define a contract that subclasses have to respect. In this way the base class or any other class can rely on this method to perform some logic. The template method uses this idea.
Suppose you have a class Warrior that has a Weapon as field, you could compute the damage performed by a Weapon thanks to this method that each subclass will have to implement :
public class Warrior{
private Weapon weapon;
// ...
public void attack(Warrior otherWarrior){
otherWarrior.receiveAttack(weapon.getDamage());
}
}
Now nothing prevents you to store the damage information that you received in Weapon subclass :
public class Knive extends Weapon {
private int damage;
public Knive(int damage){
this.damage = damage;
}
#Override
public int getDamage(){
return damage;
}
}
As explained earlier the two approaches are not opposed at all.
I don't think this is about personal taste but about the reusability, correctness, and uniformity across extending classes.
public abstract class Weapon {
protected Integer damage;
public void setDamage(Integer damage){
this.damage = damage;
}
public Integer getDamage(){
return this.damage;
}
}
public class Knive extends Weapon {
public Knive(){
setdamage(100);//or damage = 100;
}
}
The setter and getter would be the same for all of the extending classes. In case if you want to explicitly override the setter and getter for some specific result, you could override it.
It depends a lot on when and where do you want to set the value, but note that an abstract class can have field, methods and even constructors, it just can't be instantiated. so for the example you provided I prefer using this:
abstract class Weapon{
private int damage;
public Weapon(int damage) {
this.damage = damage;
}
public int getDamage() {
return damage;
}
}
class Knife extends weapon{
//damage as a parameter
public Knife(int damage) {
super(damage);
}
//damage as a default value
public Knife(){
super(100);
}
}
then you can use it this way:
Weapon knife = new Knife(100);
Weapon defaultKnife = new Knife();
System.out.print(knife.getDamage()); --->100
You can also have getter and setter methods in the parent class and you don't even have to override anything in the child class.
I have two similar class objects. I have a couple of methods for the first class object wich I also want to reuse for my second class object but I'm not sure how and I don't want to write duplicate methods.
I extracted and simplified an example to show how i think.
first class
public class FirstClass {
int number;
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
...
}
Second class
public class SecondClass {
int number;
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
...
}
Third class
public class Main {
public static void main(String[] args) {
FirstClass firstClass = new FirstClass();
firstClass.setNumber(5);
SecondClass secondClass = new SecondClass();
secondClass.setNumber(5);
numberIsFive(firstClass);
numberIsFive(secondClass);
}
public void numberIsFive(Object myObject){
if(myObject instanceof FirstClass){
myObject = (FirstClass)myObject;
}else if(myObject instanceof SecondClass){
myObject = (SecondClass)myObject;
}
if(myObject.getNumber() == 5){
System.out.println("is five");
}else{
System.out.println("is not five");
}
...
}
}
and no numberIsIFive(firsclass.getNumber()) is not an option since the methods I use have much more validations.
thanks in advance
For this case that might be "over-engineering", but in general you would look towards composition here, like:
interface IntValueHolder {
int getNumber();
void setNumber(int value);
}
class IntValueHolderImpl implements IntValueHolder { ...
And then you would "drop" the code that you currently have in both of your classes, and instead, both classes would (somehow) have an instance of IntValueHolder.
In your case, it might be more appropriate to simple have your two classes implement that "common" interface IntValueHolder - to at least avoid that repeated instanceof calls and downcast (down to a specific class).
Edit: of course, another option would be to use inheritance here - make your two classes derive from some base class that provides this behavior. But using inheritance just to avoid code duplication is most of the time a bad idea. Classes inherit from each other because that makes "sense" in the underlying model, not to save a line of code.
Before continuing I recommend you to read about it and other object oriented programming concepts by yourself.
Focusing on this particular case, you should create a base class such as
public class BaseClass {
int number;
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
}
Which includes all common fields and methods of your FirstClass and SecondClass. Then remove those methods from your two current classes, and just create them as public class FirstClass extends BaseClass to give them BaseClass functionality.
Finally, you'd have to change your validation method, to only accept objects that belong to your base class by making it like this public void numberIsFive(BaseClass myObject) (as a general rule you'll have much less errors by accepting a specific class in a method, rather than accepting any old object).
Edit: Other answerers are correct and Inheritance is also a valid solution. Which one you use would depend on what makes more sense in the context of your application.
You should create an interface and apply it in both classes, then make your validation method receive an interface instead of an Object
Example:
public interface Number {
int get();
void set(int n);
}
Then your classes will look like this:
public class FirstClass implements Number {
int number;
#Override
public int get() {
return number;
}
#Override
public void set(int n) {
this.number = n;
}
}
And your validation method receives a Number:
public void numberIsFive(Number myNumber){
...
}
public class Buildings {
public int getLevel(){
return level;
}
}
public class MainBuilding extends Buildings{
public static final int cost = 200;
public static int level = 1;
}
MainBuilding main = new MainBuilding();
main.getLevel();
I want have several building with diffrent instantsvaribles like level and cost but they should have the same method getLevel() that just returns the level. I can't find how I can do these with java...
Either move the level variable (which should probably be an instance variable, rather than a static variable) to Buildings or make getLevel() abstract so that each subclass has to implement it separately (whether that's by returning a variable, or just always returning a constant, or whatever - that's an implementation detail).
I believe their are some error in your example code. these are
you have not define level variable in Buildings class.
static method can use only static variable. (in MainBuilding variable level is static. but Building method is non-static)
here you can solve these two problem simply and execute then getlevel() function will work.
public class Buildings {
private int level;
public int getLevel(){
return level;
}
public int setLevel(l){
level = l;
}
}
public class MainBuilding extends Buildings{
public static final int cost = 200;
public MainBuilding() {
setLevel(1);
}
}
So, I can create a simple interface in C# like so:
public interface IAnimal {
int HumanYearAge { get; set; }
int AnimalYearAge { get; }
}
And then I can make an interfacing class like this:
public class Dog: IAnimal {
public int HumanYearAge;
public int AnimalYearAge
{
get { return Age * 20; }
}
}
And then in the Program I can instantiate a Dog that has a certain "HumanYearAge" and a certain "AnimalYearAge" after calculations. In Java, I have found many ways to create variables, most of which look like this:
public interface myInterface {
AtomicReference<String> Name = new AtomicReference<String>("John Doe");
//Or they look something like this:
public final int Name = 0;
}
How can I create a modifiable variable inside of a Java interface that can be PASSED DOWN (not assigned on the spot) to a class that, when instantiated as an object, can be assigned a value?
These are not variables but are called properties in C#.
And they are basically methods (in Java terms) - a getter and a setter (or one of those).
I would add getHumanYearAge (maybe also setHumanYearAge) method in your interface.
The classes implementing the interface will need to define its body (or their bodies).
And you get the same thing as in C#. It's just that Java is more verbose
(properties in C# are more concise).
Interfaces in Java do not have attributes. You need to use an abstract class.
You can have one like this.
public abstract class Animal{
private int animalYearAge;
public Animal(int animalYearAge){
this.animalYearAge = animalYearAge;
}
public void setAnimalYearAge(int age){
this.animalYearAge = age;
}
public int getAnimalYearAge(){
return animalYearAge;
}
public abstract int getHumanYearAge();
}
Then, you can define a concrete animal like this, for example.
public class Dog extends Animal{
public int getHumanYearAge(){
return this.getAnimalYearAge() * 7;
}
}
Given the folowing, in pseudocode
abstract public class Bug {
private static int BREEDTIME;
public void breed() {
if (this.age % this.BREEDTIME) {
world.setAt(new this.class(newX, newY, this.world);
}
}
}
public class Ant extends Bug {
private static int BREEDTIME = 3;
}
public class Doodlebug extends Bug {
private static int BREEDTIME = 8;
}
Is there a way to define the breed() method such that it depends on the BREEDTIME of whatever subclass is calling it? Each subclass of bug is guaranteed to have BREEDTIME initialized.
Also, Ants should breed other Ants, so the constructor called inside breed() has to be the constructor of the type of the subclass that is calling breed().
Am I barking up the wrong tree here?
I would use an abstract method to do this. Define getBreedTime() as abstract in your superclass and then implemented it in each subclass to return the appropriate constant.
You can't really do what you want using static fields like this.
It can not be done like this. Static fields are also inherited. Just remove static keyword. If you don't want to double ints then you could create abstract method to getTime or create enum:
abstract class Bug {
private int age;
public void breed() {
if (this.age % BREEDTIME.valueOf(this.getClass().getName()).getTime() == 0) {
}
}
}
class Ant extends Bug {
}
class Doodlebug extends Bug {
}
enum BREEDTIME {
Ant(3),
Doodlebug(8);
private BREEDTIME(int time) {
this.time = time;
}
public int getTime() {
return time;
}
private int time;
}