92

I wish to know is there any way in which I can make it compulsory for the implementer class to declare the objects handles/primitives as they do with methods. for e.g.:

public interface Rectangle {    
    int height = 0;
    int width = 0;

    public int getHeight();
    public int getWidth();
    public void setHeight(int height);
    public void setWidth(int width);                
}


public class Tile implements Rectangle{
    @Override
    public int getHeight() {
        return 0;
    }

    @Override
    public int getWidth() {
        return 0;
    }

    @Override
    public void setHeight(int height) {
    }

    @Override
    public void setWidth(int width) {   
    }

}

In the above method how can we compel Tile class to declare height and width attributes using the interface? For some reason I wish to do it with interface only!

I initially thought of using it with inheritance. But thing is I have to deal with 3 classes.!

  1. Rectangle
  2. Tile
  3. JLabel.!

 

 class Tile extends JLabel implements Rectangle {}

would work.!

but

class Tile extends JLabel extends Rectangle {}

woud not.!

cwallenpoole
  • 79,954
  • 26
  • 128
  • 166
Shrey
  • 2,374
  • 3
  • 21
  • 24
  • 8
    Your interface is incorrect. It can't contain attributes. Maybe you want to use an abstract class? – pvoosten Sep 05 '11 at 17:48
  • 10
    @lbp That [will actually compile](http://www.coderanch.com/t/178630/java-SCJA/certification/Instance-variables-interface) ;-) It is just ... not the "expected" behavior. The compiler assumes/applies a `final static` modifier. –  Sep 05 '11 at 17:57
  • 1
    You might like to use Height instead of Hieght and Hight. Hight is the past participle of highten, hihten, to call, be called. ;) – Peter Lawrey Sep 05 '11 at 17:58
  • If you provide accessors, why would you want to expose the variables? – Jonathan Leffler Sep 05 '11 at 18:29
  • You can have constants in an interface, but that's about it and even then you would be hard pressed to find a scenario in which using such would not be contrived. – Wim Ombelets Sep 12 '14 at 15:29
  • You are doing it wrong i think. An interface can extend multiple interface but a class can't. As java only allows single inheritance. – Sajidur Rahman Oct 05 '15 at 05:51

10 Answers10

112

The point of an interface is to specify the public API. An interface has no state. Any variables that you create are really constants (so be careful about making mutable objects in interfaces).

Basically an interface says here are all of the methods that a class that implements it must support. It probably would have been better if the creators of Java had not allowed constants in interfaces, but too late to get rid of that now (and there are some cases where constants are sensible in interfaces).

Because you are just specifying what methods have to be implemented there is no idea of state (no instance variables). If you want to require that every class has a certain variable you need to use an abstract class.

Finally, you should, generally speaking, not use public variables, so the idea of putting variables into an interface is a bad idea to begin with.

Short answer - you can't do what you want because it is "wrong" in Java.

Edit:

class Tile 
    implements Rectangle 
{
    private int height;
    private int width;

     @Override
    public int getHeight() {
        return height;
    }

    @Override
    public int getWidth() {
        return width;
    }

    @Override
    public void setHeight(int h) {
        height = h;
    }

    @Override
    public void setWidth(int w) { 
        width = w;  
    }
}

an alternative version would be:

abstract class AbstractRectangle 
    implements Rectangle 
{
    private int height;
    private int width;

     @Override
    public int getHeight() {
        return height;
    }

    @Override
    public int getWidth() {
        return width;
    }

    @Override
    public void setHeight(int h) {
        height = h;
    }

    @Override
    public void setWidth(int w) { 
        width = w;  
    }
}

class Tile 
    extends AbstractRectangle 
{
}
TofuBeer
  • 60,850
  • 18
  • 118
  • 163
  • kk! so how do I go about it.?? (I have edited the question, pls check)! – Shrey Sep 07 '11 at 14:27
  • This will help I suppose..! thnxx :) – Shrey Sep 08 '11 at 11:51
  • But that leaves the problem that you cannot mess with height in the concrete implementation. So you know you need a height, you know you need to be able to return height, but you cannot leave it to each implementation to calculate height (which I think defeats the purpose). Of course you can declare `getHeight` abstract and not declare height at all, but then you have to repeat the return code every time, just so you can keep the variable private. – alianos- Apr 04 '13 at 15:27
  • 1
    -1 for "The point of an interface is to specify the public API. An interface has no state."; an interface has no state, but as far as an interface is concerned, public member variables are part of the object's public API. Unfortunately in Java-land, a public member variable is specifying something about the implementation of that API (namely that it's an in-memory variable) rather than leaving yourself the flexibility to change the implementation. In other words, `obj.Property` can never invoke any other code, but `obj.Property()` can, & the two are treated differently at the interface level. – weberc2 Aug 05 '14 at 18:35
19

Interfaces cannot require instance variables to be defined -- only methods.

(Variables can be defined in interfaces, but they do not behave as might be expected: they are treated as final static.)

Happy coding.

10

Java 8 introduced default methods for interfaces using which you can body to the methods. According to OOPs interfaces should act as contract between two systems/parties.

But still i found a way to achieve storing properties in the interface. I admit it is kinda ugly implementation.

   import java.util.Map;
   import java.util.WeakHashMap;

interface Rectangle
{

class Storage
{
    private static final Map<Rectangle, Integer> heightMap = new WeakHashMap<>();
    private static final Map<Rectangle, Integer> widthMap = new WeakHashMap<>();
}

default public int getHeight()
{
    return Storage.heightMap.get(this);
}

default public int getWidth()
{
    return Storage.widthMap.get(this);
}

default public void setHeight(int height)
{
    Storage.heightMap.put(this, height);
}

default public void setWidth(int width)
{
    Storage.widthMap.put(this, width);
}
}

This interface is ugly. For storing simple property it needed two hashmaps and each hashmap by default creates 16 entries by default. Additionally when real object is dereferenced JVM additionally need to remove this weak reference.

Dungeon Hunter
  • 19,827
  • 13
  • 59
  • 82
  • 2
    Quite interesting but weird :). You may even eliminate inner class and just store static final maps in your interface itself. – iMysak Sep 20 '17 at 17:59
8

You can only do this with an abstract class, not with an interface.

Declare Rectangle as an abstract class instead of an interface and declare the methods that must be implemented by the sub-class as public abstract. Then class Tile extends class Rectangle and must implement the abstract methods from Rectangle.

Simon C
  • 1,977
  • 11
  • 14
  • I initially thought of using it with inheritance. But thing is I have to deal with 3 classes.! 1. Rectangle 2. Tile 3. JLabel.! class Tile extends JLabel implements Rectangle {} would work.! but class Tile extends JLabel extends Rectangle {} woud not.! – Shrey Sep 07 '11 at 14:19
3

In Java you can't. Interface has to do with methods and signature, it does not have to do with the internal state of an object -- that is an implementation question. And this makes sense too -- I mean, simply because certain attributes exist, it does not mean that they have to be used by the implementing class. getHeight could actually point to the width variable (assuming that the implementer is a sadist).

(As a note -- this is not true of all languages, ActionScript allows for declaration of pseudo attributes, and I believe C# does too)

cwallenpoole
  • 79,954
  • 26
  • 128
  • 166
  • 1
    In C# *getters/setters* (which are really just special method calls) can be in interfaces -- instance variables themselves cannot. –  Sep 05 '11 at 18:02
  • That's what I thought (and that's why I said pseudo) ActionScript does the same thing. – cwallenpoole Sep 05 '11 at 18:22
  • kk!! inheritance instead of implementation would help.! But this would arise me a new problem..! can you suggest me the way to go about it? (see the edited question) thnx!! – Shrey Sep 07 '11 at 14:34
1

Like everyone says, you cannot add attributes to an interface.

But, I follows this answer: https://stackoverflow.com/a/25907755/12955288 You can use an service with a WeakHashMap to store attributes.

To reduce maps, use a Map of keys like this:

In java 11:

public interface Rectangle {

    class Storage {
        private static final Map<Rectangle, Map<String, Object>> attributes = new WeakHashMap<>();
    }

    private Map<String, Object> getAttributes(){
        return Storage.attributes.computeIfAbsent(this, k -> new HashMap<>());
    }

    default public int getHeight() {
        return (int) getAttributes().getOrDefault("height", 0);
    }

    default public int getWidth() {
        return (int) getAttributes().getOrDefault("width", 0);
    }

    default public void setHeight(int height) {
        getAttributes().put("height", height);
    }

    default public void setWidth(int width) {
        getAttributes().put("width", width);
    }
}
iriiko
  • 43
  • 4
1

Fields in interfaces are implicitly public static final. (Also methods are implicitly public, so you can drop the public keyword.) Even if you use an abstract class instead of an interface, I strongly suggest making all non-constant (public static final of a primitive or immutable object reference) private. More generally "prefer composition to inheritance" - a Tile is-not-a Rectangle (of course, you can play word games with "is-a" and "has-a").

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
0

Something important has been said by Tom:

if you use the has-a concept, you avoid the issue.

Indeed, if instead of using extends and implements you define two attributes, one of type rectangle, one of type JLabel in your Tile class, then you can define a Rectangle to be either an interface or a class.

Furthermore, I would normally encourage the use of interfaces in connection with has-a, but I guess it would be an overkill in your situation. However, you are the only one that can decide on this point (tradeoff flexibility/over-engineering).

msrd0
  • 7,816
  • 9
  • 47
  • 82
bal
  • 1
0

For interfaces with member variables, use an abstract class:

public abstract class Rectangle {    
    int height = 0;
    int width = 0;

    public abstract int getHeight();
    public abstract int getWidth();
    public abstract void setHeight(int height);
    public abstract void setWidth(int width);                
}
Nirvana
  • 405
  • 3
  • 15
0

An ancillary point:

I always thought declaring attributes in an interface is sort of an anti-pattern as interfaces are stateless. And I haven't had a practical use case for it until I required dependency injection on all the concrete classes implementing the interface. While I could manually inject the dependencies on each class, it would be easier to inherit them from a parent class.

So, as many people have already mentioned, using an Abstract class is the way to go where the dependency can be injected (@Inject), and all the child classes could extend this and override (@Override) the methods while using the attributes of the parent class.

Rahul
  • 543
  • 1
  • 7
  • 24