Blankman
Blankman

Reputation: 266978

Could I convert this method using generics?

I currently have the following method in a class which I hope I can push to a superclass since I will have a few other classes which will need similar functionality.

public long convertToLong(EnumSet<SomeTypeHere> es) {

  long a = 0;

  for(SomeTypeHere sth : es) {
     a += sth.someLongProperty();

  }
}

It would be great if I can do this, I've never really used java generics before other than with collections.

Upvotes: 3

Views: 90

Answers (4)

PaulMurrayCbr
PaulMurrayCbr

Reputation: 1260

yep - java intersection types (Bohemian's answer) do what you want. I had a similar issue where I had a number of enum classes that I all wanted to have a getDescription() method.

In general, intersection types get around the issue that you can't subclass enums.

Upvotes: 0

Bohemian
Bohemian

Reputation: 424993

This code below does what you need. The key is the use of the generic syntax that bounds a type to multiple types - in this case an Enum and your interface.

This compiles:

public interface HasSomeLongProperty {
    long someLongProperty();
}

public static enum Fruit implements HasSomeLongProperty {
    apple(1),
    orange() {
        // You may override the default implementation and delegate
        public long someLongProperty() {
            // You could also make this a field and not new every call
            new SomeHasSomeLongPropertyImpl().someLongProperty();
        }
    };

    private long value;

    private Fruit() {
    }

    private Fruit(long value) {
        this.value = value;
    }

    public long someLongProperty() {
        return value;
    }
}

public static <T extends Enum<T> & HasSomeLongProperty> long convertToLong(EnumSet<T> es) {
    long a = 0;
    for (T sth : es)
        a += sth.someLongProperty();
    return a;
}

Upvotes: 2

Alex D
Alex D

Reputation: 30445

You will need to put a bound on the generic type. If the class which contains convertToLong is parameterized on the same type, you can put the bound there:

import java.util.*;
public class GenericTest<C extends GenericTest.HasLongProperty> {
    static interface HasLongProperty {
        long someLongProperty();
    }
    public long convertToLong(Collection<C> es) {
        long a = 0;
        for(C sth : es)
            a += sth.someLongProperty();
        return a;
    }
}

Or if the class which contains convertToLong is not generic, you can put the bound in the declaration of that one method alone:

import java.util.*;
public class GenericTest {
    static interface HasLongProperty {
        long someLongProperty();
    }
    public <C extends GenericTest.HasLongProperty> long convertToLong(Collection<C> es) {
        long a = 0;
        for(C sth : es)
            a += sth.someLongProperty();
        return a;
    }
}

Upvotes: 3

Peter
Peter

Reputation: 679

I think you want something like this:

public <T extends SomeType> long convertToLong(Collection<T> es) {

    long a = 0;

    for(T sth : es) {
       a += sth.someLongProperty();

    }
    return a;
  }

This says that you can pass in a Set of type T where T can be any subclass of SomeType and SomeType has the function someLongProperty.

Upvotes: 2

Related Questions