Question

I'm creating something like this and got struck about the usage of generics in java.

Idea: Producer produces something of type T and consumers contains command objects, command objects holds different mediators. Mediators holds objects of type Subject and updates values of type T

Note: I'm doing this to understand how generics works in terms of inheritance of the generic types and composition of the type parameter definitions in generic type intefaces and concrete classes, so please don't bother about rationale of the design.

Interfaces definitions:

Composition:

  1. IObserver

  2. ISubject which holds object of type T and IObserver.

  3. IMediator holds objects of type ISubject and type T

  4. ICommand holds objects of type IMediator and type T

  5. IProducerConsumer holds objects of type T and ICommand.

There are some concrete Objects for the corresponding interfaces. I defined interfaces like this:

public interface IObserver<T>
public interface ISubject<T,O extends IObserver<T>>

Cool until now. But Now the problems started.

public interface IMediator<T,S extends ISubject<T,O>, O extends IObserver<T>>

compiler is forcing me to do this. I mean O extends IObserver<T> as above. So, I infered that I can't define like below

public interface IMediator<T,S extends ISubject<T,O extends IObserver<T>> >

I concluded: that inner type parameter definition must not be expanded as above. So, finally happy with public interface IMediator<T,S extends ISubject<T,O>, O extends IObserver<T>> Now mess started in ICommand public interface ICommand <T,M extends IMediator<T, ?, ?>>,

I'm struck now compiler is not accepting many of my possibilities even what inference i made as above. I mean

public interface ICommand <T,M extends IMediator<T, S, o>, S extends ISubject<T, IObserver<T>>,O extends IObserver<T>>

is not working. I don't want to user wild card I want to tell to the compiler something more concrete.

My questions are:

  1. Is my inference correct as in ICommand definition.

  2. How to interpret the above case studies.

  3. What are the best defintions assuming that I want to insert T and must able to get and put.

  4. What is the rules and relations of the type parameter definitions in interface and implemented classes.

Please explain ?

Was it helpful?

Solution

Generics with Bound Parameters (no wildcards)

  • Is my inference correct as in ICommand definition?

    No. Two reasons
    1. You have written a small 'o' while passing it to Mediator. (I guess it's just a typing mistake.)
    2. You passed IObserver<T> in stead of O to ISubject which would definitely cause a parameter bound mismatch.

Correct Version:

interface ICommand<T, M extends IMediator<T, S, O>, S extends ISubject<T, O>, O extends IObserver<T>>

  • How to interpret the above case studies?

    1. The first thing you'd need to understand that you have one unknown type T and five interfaces.
    2. Therefore you would have total six concrete types which have to be included progressively in the interface declarations. (You explicitly asked not to bother about rationale of the design.)
    3. If you write them in a correct order, it becomes much more manageable.

Interface declarations:

interface IObserver<T>

interface ISubject<T, O extends IObserver<T>>

interface IMediator<T, O extends IObserver<T>, S extends ISubject<T,O>>

interface ICommand<T, O extends IObserver<T>, S extends ISubject<T, O>, 
                   M extends IMediator<T, O, S>>

interface IProducerConsumer<T, O extends IObserver<T>, S extends ISubject<T, O>,
                   M extends IMediator<T, O, S>, C extends ICommand<T, O, S, M>>

  • What are the best defintions assuming that I want to insert T and must able to get and put?

    1. If you want to get and put object of type T, what you probably need is bunch of interfaces which take only one parameter T. Generics will enforce that all would be compatible as T will be replaced by same type everywhere.
    2. Your current system is too rigid. In real scenario, you would never have so many implementations of these interfaces (unless you are re-implementing facebook in java) so that you'd have many possible combinations of the implementations and you want to ensure compatibility.
    3. Generics enforces type-safety by applying restrictions which are good. But you should not put restrictions just because you can put them. You are losing flexibility, readability and maintainability of your code.
    4. You should add bounds only when you need them. They should not affect the design in any way before contracts between interfaces have been decided.

Possibly sufficient way:

interface IObserver<T>

interface ISubject<T>

interface IMediator<T>

interface ICommand<T>

interface IProducerConsumer<T>

  • What is the rules and relations of the type parameter definitions in interface and implemented classes?

    1. The only relation between type parameters in interfaces and implementing class that I can think of is that implementing class has to provide a type to replace the generic type parameter.
    2. In some cases, that type can again be a generic type in which case the responsibility of providing concrete type is forwarded to the code using the class reference or another class which extends that class. It may even be recursive!
    3. The rules are not written in the language, in stead, you are applying all the rules on this mechanism when you make any type parameter bound. So as long as you are supplying a type which qualifies against all of your rules, you are good to go.
    4. More rules means more robust but less flexible/readable. So do the trade of wisely.

Two simple cases:

// General way
private class ProductObserver implements IObserver<Product> { }

private ProductObserver productObserver;

// Aspect oriented way
private class LoggerObserver<T> implements IObserver<T> { }

private LoggerObserver<Product> loggerObserver;

  • Lastly, I'd suggest you to read (comprehensive) Java Generics FAQ by Angelika Langer if you have any further doubt.
  • If you keep experimenting like this, you might as well end up inventing a design pattern. Don't forget to share it with us when you do :D

Hope this helps.
Good luck.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top