5

I am writing a class to represent time series data, i.e. basically a map of (Instant, T) pairs for a generic type T

interface TimeSeries<T> {
     void add(Instant when, T data);
}

Some of the classes we deal with implement an interface

interface TimeStamped {
    Instant getTimeStamp();
}

and I want to provide a more convenient method in the TimeSeries interface to add such data items without stating the time explicity. Basically, I want

interface TimeSeries<T> {
     void add(Instant when, T data);
     default <X extends T & TimeStamped> void add(X data) {
         add(data.getTimeStamp(), data);   
     } 
}

but this seems not allowed by the language because I cannot use type variables in intersection types. Is there a work-around that does not involve giving up static type-safety? The only things I can come up with are

interface TimeSeries<T> {
     void add(Instant when, T data);
     default void add(TimeStamped data) {
         add(data.getTimeStamp(), (T)data);   
     }
     default void add(TimeStamped t, T data) {
         add(t.getTimeStamp(), data);
     } 
}

add(TimeStamped t, T data) is type-safe but still inconvenient.

9
  • 4
    A simple workaround would be a interface TimeStampedTimeSeries<T extends TimeStamped> extends TimeSeries<T> - you could use it when populating the timeseries and when consuming it you could just refer to TimeSeries<?>. Commented Oct 24, 2017 at 14:01
  • Another workaround is to use a static method static <X extends TimeStamped> void add(TimeSeries<? super X> timeSeries, X x) Commented Oct 24, 2017 at 14:30
  • @cppbeginner that one however doesn't bring any extra simplicity. Commented Oct 24, 2017 at 14:34
  • 1
    Why not? OP wants to write timeSeries.add(x). Instead you can write add(timeSeries, x). Commented Oct 24, 2017 at 14:37
  • 1
    @Vlasec I created a TimeStamped-only interface. The generic interface is just used to define the data structure in an application-agnostic way, and in the application we can use the TimeStamped-only interface. Commented Oct 26, 2017 at 9:22

1 Answer 1

1

I guess I understand your question. Basically, you could have a TimeSeries with some simple type that doesn't implement TimeStamped, but some of its subclasses do. In those cases, not even the workaround by @assylias helps.

Well, I think there is no clean solution for this problem in Java 8, and I have no experience with Java 9, but I didn't notice anything like that while reading about its new features. That means you either sacrifice static type safety or comfort.

It is kinda hard to tell what is the best workaround. Basically what we have here so far is:

  • TimeStamped-only interface for the cases where your base object already implements the TimeStamped interface, as advised by @assylias.
  • Static method as advised by @cppbeginner. I don't like the syntax though, it is meant as syntax sugar, but you end up with a static call. It's quite versatile though and does what you want.
  • Give up on the syntax sugar idea entirely and just type it like a slave.
  • Give up type safety and have a nice code that can backfire.
  • Oh wait, one more possibility. Make it a method of TimeStamped interface instead, with the TimeSeries as an argument. Actually better than going static, but kinda bottom up.

I can't decide which one is better for you as I don't know your use case. None of them is perfect. I already encountered this issue and I found no super-smart solution either. Another thing I was unable to do is a generic enum. I mean, why not, it would be interesting if it was possible (but it's not, either).

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.