I know that I can't do this:
public abstract class DTODomainTransformer<T, S> {
public abstract S transform(T);
public abstract T transform(S);
}
Because I get the compiler complaint:
Method transform(T) has the same erasure transform(Object) as another method in type Transformer<T,S>
I understand that is because both T
and S
could be extending same class. So doing this way i can tell him "No, they are not the same, so take it easy"
public interface Transformer<T extends AbstractDTO , S extends AbstractDomain> {
public abstract S transform(T object);
public abstract T transform(S object);
}
Then, my question is, is there any way to tell the compiler that T
and S
extend from different classes without telling which ones in concrete? I mean, in this last case, I've specified which classes had to be T
and S
(extending respectively). But what if I want it more generic and not specify them? I'd like to tell the compiler, "Hey, compiler, T
and S
are not the same! They are different classes. I don't know exactly which classes they are, but I'm sure that they are different".
No, you cannot overload a method based on different return type but same argument type and number in java. same name. different parameters (different type or, different number or both).
i.e. the methods can have the same name but with different parameters list (i.e. the number of the parameters, the order of the parameters, and data types of the parameters) within the same class.
Answer: Yes, we can overload a generic methods in C# as we overload a normal method in a class.
Method overloading is possible only if the overloaded methods have different signatures. It cannot be possible if the signature is same and only the return type is different.
There's not an obvious way. (Although you can build one, as I show below.)
This overload rule is due to a limitation of how the supertype (in this case, interface) that declares the overloads gets translated (by erasure) to bytecode.
If there's a generic parameter declared T
, a method that uses T
in its signature will have bytecode generated as the upper bound of T
, for example
class Generic<T> {
void work(T t) {}
}
will get erased to
class Generic {
void work(Object t) {}
}
and
class Generic<T extends Number> {
void work(T t) {}
}
will get erased to
class Generic {
void work(Number t) {}
}
This is how the bounded example works, because the overloads erase differently.
public interface Transformer {
public abstract AbstractDomain transform(AbstractDTO object);
public abstract AbstractDTO transform(AbstractDomain object);
}
But without specific bounds, what erased bytecode should be generated for the overloaded methods?
So your T
and S
being different on the subtype is not what's important. What is important is the known declared bounds which get translated to erased bytecode for the supertype class.
A possible solution could use marker interfaces.
interface TransformT {}
interface TransformS {}
interface Transformable extends TransformT, TransformS {}
interface Transformer<T extends TransformT, S extends TransformS>
T transform(S s);
S transform(T t);
}
abstract class AbstractDTO implements Transformable {}
abstract class AbstractDomain implements Transformable {}
new SomeTransformerImpl<AbstractDTO, AbstractDomain>()
But I don't necessarily recommend doing this. It seems elaborate to me, although interesting. It depends on how complicated the actual class hierarchy is.
What Louis suggested in the comments is much simpler: give the methods different names.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With