views:

107

answers:

2

I want to force a class to define a certain variable from the class it implements. e.g.

class Fruit{
     String name; // Cause each fruit has a name
}

//Apple wants to get an error if it does not use the name variable
class Apple implements Fruit {
     String name = "Apple";
}

Is there a way to do that? Just like java.io.Serializable does it?

+7  A: 

The easiest way, I suppose, is using the constructor.

class Fruit{
     private final String name; 
     public Fruit(String name){ 
         if (/* name has an incorrect value, is null or whatever */) 
             throw new IllegalArgumentException("name");
         this.name = name; 
     }
}

//Apple wants to get an error if it does not use the name variable
class Apple extends Fruit {
     public Apple(){ super("Apple"); }
}

Now it's impossible to make a Fruit subclass which doesn't pass a name to the Fruit constructor. By making the field final, you also get the added bonus that once the field has been set to a proper value, subclasses can't put bogus stuff there (except for using reflection etc, but then all bets are off).

Edit: Also, as pointed out by more attentive posters, you don't implement classes, you extend them. For interfaces (which you do implement), you can't enforce that sane values are returned from the methods (not in any easy way - I suppose you could use AOP to check the return values and throw an IllegalStateException when bogus values are returned).

gustafc
does that compile?
akf
D'oh. Thanks :)
gustafc
@akf I changed the keyword to reflect your judicious comment.
KLE
+1: finals + constructor are definitely the way to go. One other option (though potentially of the enough-rope-to-shoot-yourself-in-the-foot variety - since subclasses can now get by without a constructor) this route affords: you can specify an empty constructor in Fruit which sets the final fields with default values.
Carl
+2  A: 

You can't override variables in Java. Just use a interface with setter/getters or the constructor variant from gustafc. Here's an quick'n'dirty example:

interface Fruit {
  String getName();
  void setName(String name);
}

class Apple implements Fruit {
  private String myName="";

  public void setName(String name) { myName=name;}
  public String getName() { return myName;}
}

I personally favor the constructor variant, so things wont get null.

dz