0

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?

Zac G
  • 125
  • 2
  • 17
  • 4
    `how to create variables in java interfaces`: ...............don't. Either use an abstract class if you *absolutely* need fields, use the interface and let the concrete classes declare their own fields. – Hovercraft Full Of Eels Nov 17 '15 at 20:43
  • 3
    You cannot define dynamic field in interfaces, only static ones. You could instead define getters instead of dynamic fields. But I agree with @HovercraftFullOfEels 's approach to create an abstract class. – Turing85 Nov 17 '15 at 20:43
  • @HovercraftFullOfEels I already said, I **Can't** use classes - even abstract classes - as I need classes to be able to implement (or extend in classes case) them more than once. – Zac G Nov 17 '15 at 20:47
  • @Turing85 Would a static interface act the same way as a static class, as in keeping the variables the same between all classes that implement it? – Zac G Nov 17 '15 at 20:48
  • 2
    Zac -- OK, then it's very clear that what you're trying to do -- make an interface into an abstract class -- is not going to work. – Hovercraft Full Of Eels Nov 17 '15 at 20:48
  • @ZacG [In addition, an interface can contain constant declarations. All constant values defined in an interface are implicitly public, static, and final. Once again, you can omit these modifiers.](https://docs.oracle.com/javase/tutorial/java/IandI/interfaceDef.html) They act the same way as they would within a class. – Turing85 Nov 17 '15 at 20:49
  • Okay then, what should I use then. I can't use abstract classes because you can't extend more than 1 class... – Zac G Nov 17 '15 at 20:52
  • @ZacG as I described in my first comment: create methods like `getRange()` and `getDamage()` instead of the dynamic fields is one option. – Turing85 Nov 17 '15 at 20:53
  • That's true, I'll do that – Zac G Nov 17 '15 at 20:54

4 Answers4

2

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)

NickJ
  • 9,380
  • 9
  • 51
  • 74
  • I suppose that could work, I'll try it. Although, it will be a bit annoying to have to create the variables each time. – Zac G Nov 17 '15 at 20:50
  • You won't have to - your classes will extend `AbstractDefenseBuilding` and inherit the variables. – NickJ Nov 17 '15 at 20:51
  • What if I wanted to have a building which was a defence building and, say, a house? – Zac G Nov 17 '15 at 20:53
  • I don't know what a house is in your context. – NickJ Nov 17 '15 at 20:54
  • A house would be another building type (Same as DefenseBuilding) – Zac G Nov 17 '15 at 20:55
  • @ZacG One possibility might be to have a house which has a list of features, like being a defense building, instead of expressing this as an intersection of interfaces. – Louis Wasserman Nov 17 '15 at 20:59
  • If House is another interface, then classes can extend AbstractDefenseBuilding and implement House – NickJ Nov 17 '15 at 21:01
1

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 (){...}
}
reos
  • 8,766
  • 6
  • 28
  • 34
0

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.

Aragorn
  • 5,021
  • 5
  • 26
  • 37
  • @HarryHarrison lookup, any variable in Java Interface are static and final by default. Hope you remove that down vote after you read some documentation. – Aragorn Nov 17 '15 at 21:25
  • @HarryHarrison here's some links for you: http://stackoverflow.com/questions/2430756/why-are-interface-variables-static-and-final-by-default?answertab=active#tab-top – Aragorn Nov 17 '15 at 21:28
  • 1
    @HarryHarrison Interface fields are implicitly `static` and `final`, and while a "final variable" may seem semantically impossible, we abide by the rules of the `JLS` and nothing else. (I evened out the score) – Kayaman Nov 17 '15 at 21:39
  • @HarryHarrison I didn't ask you to upvote, just asked you to remove your downvote if you agree with me. – Aragorn Nov 17 '15 at 21:42
  • @Aragorn - something I would gladly do if SO let me. – Harry Harrison Nov 17 '15 at 21:44
0

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;
  }
}
Bobby StJacques
  • 724
  • 4
  • 9