Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I've need an interface that assures me a certain method, including specific signature, is available. So far his is what I have:

public interface Mappable<M> {
    M mapTo(M mappableEntity);
}

The problem arises when a class should be mappable to multiple other entities. The ideal case would be this (not java):

public class Something implements Mappable<A>, Mappable<B> {
    public A mapTo(A someObject) {...}
    public B mapTo(B someOtherObject) {...}
}

What would be the best way to achieve this remaining as "generic" as possible?

share|improve this question
add comment

3 Answers

up vote 3 down vote accepted

This is, of course, not something you can do due to Type Erasure. At runtime, you have two methods public Object mapTo(Object), which obviously cannot coexist.

Unfortunately, what you are trying to do is simply beyond Java's type system.

Assuming your generic type is always a first class type, and not itself generic, you could achieve similar outward-facing behaviour by having the method mapTo(Object, Class), which would allow you to do runtime inspection of the given class and decide which behaviour to use. Obviously this is pretty inelegant--and will require manual casting of the return value--but I think it's the best you can do. If your generic types are themselves generic, then their generic parameters will be erased too and their Classes will be equal, so this method won't work.

However, I would point towards @Joachim's answer as well, this may be a case where you can split the behaviour out into separated components and sidestep the whole issue.

share|improve this answer
add comment

As you saw, you can't implement the same interface twice with different type parameters (because of erasure: at runtime they are the same interfaces).

Also, this approach violates the single responsibility principle: your class should focus on being a Something (whatever that means) and should not do the mapping to A or B in addition that task.

It sounds like you really should have a Mapper<Something,A> and a Mapper<Something,B>. This way each class has a single clearly-defined responsibility and you don't run into the problem of implementing the same interface twice.

share|improve this answer
 
Well, the idea is to let the class be responsible for "transforming" its contents to other objects. Then there's a dispatcher that handle them in a Class agnostic manner, therefore the generics requirement. I'll think a bit about extracting the logic, though that actually means I'm splitting the class in two, but they remain tightly coupled (access to field should be granted, modifying one most of the times imply modifying the other, etc) –  estani Nov 25 '13 at 9:45
 
@estani: yes, they are somewhat tightly coupled, but they have distinct responsibilities. Also think about this: when you introduce a new class C and you want Something to be mappable to that, then you'd need to modify Something, which is too much coupling. Just adding a new SoemthingToCMapper is less intrusive. –  Joachim Sauer Nov 25 '13 at 9:50
 
+1 to this - generally speaking you should favour composition over inheritance if you're trying to achieve what the OP wants (in Java). Java 8 with default methods makes this even easier - but not everyone can jump on the bleeding edge yet :-). –  Martijn Verburg Nov 25 '13 at 10:11
add comment
public interface IMappable<S, T> {
    T MapFrom(S source);
}

// T - target
// S - source

If you want to map User to UserDTO and map User to UserViewModel, then you'll need two separate implementations. Don't pile up all this logic into a single class - it doesn't make sense to do that.

Update to keep Joachim happy

public interface ITypeConverter<TSource, TDestination>
{
    TDestination Convert(TSource source);
}

But now we are in the Automapper realm (http://automapper.codeplex.com/wikipage?title=Custom%20Type%20Converters)

share|improve this answer
 
I don't think IMappable is a good name for something that maps other things. Mapper (or IMapper, if you must ;-)) is probably more correct. (By the way: no, that was not my downvote). –  Joachim Sauer Nov 25 '13 at 9:49
 
I have taken what was in the question and prefixed with an I to highlight the fact it's an interface. I'm solving design problem as per question, as opposed to a naming problem. –  CodeART Nov 25 '13 at 9:52
1  
sorry, but in my opinion one can not really "solve" a design problem and ignore naming. Design means understandable structures. Wrong naming is a problem to understanding. –  Joachim Sauer Nov 25 '13 at 9:54
 
Update should put your mind at rest ;-) –  CodeART Nov 25 '13 at 10:02
1  
@CodeART If I understood your answer correctly it implies "MapFrom" (which should be lowercased ;-) creates the object. In my case it's just filling information on an already created object. –  estani Nov 25 '13 at 10:06
show 1 more comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.