开发者

Requiring enums of extending classes

I would like to require classes that extend my abstract class A to provide an enumerated type. I don't need to constrain the type itself, I just want to ensure that they provid开发者_如何学运维e some enumerated type. For example, I have an abstract class Animal and I want to ensure that every Animal has a set of behaviors. I don't need to constrain these behaviors or create a master list in any way; I just want to ensure that all Animals return a list of symbolic behaviors.

Ideally, I would like to say:

public abstract class Animal {
  public List<Enum> getBehaviors(); 
}

but this won't compile cleanly.

Any ideas? Would it be better to approach this via Generics?


Ok, I'm going to expand my comment a bit here.

If you want to have your getBehaviors() method return a list of behaviors for a particular animal, making the method signature declare that a List<Enum<?>> is returned does nothing to help you. A client who gets your List<Enum<?>> from that method isn't able to do anything useful with it (who knows what it is?). The restriction also doesn't do anything to help ensure that the type of objects the behaviors list contains are actually "behaviors", whatever that means to in the context of your application. They could be days of the week, months of the year or just about anything!

What I'm guessing is that you have some enums like DogBehavior (with constants like BARK, BITE, etc.) and you want to ensure that only such behaviors are allowed in the list. The fact that these behaviors are collected in enums is an implementation detail. What you should do is introduce a common interface that designates something as a Behavior. If there aren't any specific methods associated with a Behavior, it could just be a marker interface (that defines no methods). Otherwise, you might want it to have some methods, like such:

public interface Behavior {
  public String getName();
  public void doBehavior();
  // etc.
}

You could then have some enums that implement this interface:

public enum DogBehavior implements Behavior {
  BARK("Bark") {
    public void doBehavior() {
      // bark
    }
  },
  // etc.

  private final String name;

  DogBehavior(String name) {
    this.name = name;
  }

  public String getName() {
    return name;
  }
}

Then, 'Animal' might look like:

public abstract class Animal {
  public abstract List<Behavior> getBehaviors(); 
}

Which makes a lot more sense to me.


I'm a bit confused - if you want to require all Animals to export a set of behaviors, then ideally your goal would be to be able to write something like this:

Animal a = /* .. create some subtype of Animal .. */
List</* ?? */> behaviors = a.getBehaviors();

The problem here is that if you want each Animal create its own enumerated type for behaviors, you have no unified way of talking about those behaviors unless you explicitly specify some type that represents them. In other words, you can't fill in the /* ?? */ above unless in the Animal interface you provide a type that all Animal behaviors should be related to.

One option would be to define a class like this one:

public final class Behavior {
    private final String name;

    public Behavior(String name) {
        this.name = name;
    }
    public String getBehaviorName() {
        return name;
    }
    /* ... etc. ... */
}

Then, you could have each Animal type define getBehaviors() so that it returns a list of Behavior objects. This gives you a type-safe framework for discussing behaviors, and potentially the ability to add more complex actions for each behavior.


2 things I see wrong.

First, you need to mark that method abstract. You didn't provide an implementation.

Second, the Enum should be parameterized if you don't want a warning. Enum<?> should be enough if you don't need to restrict the Enum further.

However, as others have noted, this probably is NOT what you want. An Enum of "behaviors" is useless to you. They have no functionality once returned from getBehaviors(). You could iterate through them and list them, but that's worth nothing more than a List<String>.

I would think that you want a List<Behavior> where Behavior is an interface that DOES something for you.

EDIT: ColinD above beat me to the punch on the same point.


public abstract class Animal {
  public List<? extends Enum<?>> getBehaviors(); 
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜