Implementazione di più interfacce generiche in java

10

Ho bisogno di un'interfaccia che mi assicuri un determinato metodo, inclusa la firma specifica, è disponibile. Finora il suo è quello che ho:

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

Il problema sorge quando una classe deve essere mappabile a più altre entità. Il caso ideale sarebbe questo (non java):

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

Quale sarebbe il modo migliore per ottenere ciò che rimane come "generico" possibile?

    
posta estani 25.11.2013 - 09:59
fonte

4 risposte

10

Questo, naturalmente, non è qualcosa che puoi fare a causa della Cancellazione di tipo . Al momento dell'esecuzione, hai due metodi public Object mapTo(Object) , che ovviamente non possono coesistere.

Sfortunatamente, quello che stai cercando di fare è semplicemente al di là del sistema di tipi di Java.

Supponendo che il tuo tipo generico sia sempre un tipo di prima classe, e non di per sé generico, potresti ottenere un comportamento simile verso l'esterno avendo il metodo mapTo(Object, Class) , che ti permetterebbe di fare il controllo in runtime della classe data e decidere quale comportamento da usare. Ovviamente questo è piuttosto inelegante e richiederà la fusione manuale del valore di ritorno, ma penso che sia il meglio che puoi fare. Se i tuoi tipi generici sono generici, anche i loro parametri generici verranno cancellati e le loro classi saranno uguali, quindi questo metodo non funzionerà.

Tuttavia, vorrei puntare anche alla risposta di @ Joachim, questo può essere un caso in cui puoi dividere il comportamento in componenti separati e aggirare l'intero problema.

    
risposta data 25.11.2013 - 10:35
fonte
3

Come hai visto, non puoi implementare la stessa interfaccia due volte con parametri di tipo diversi (a causa della cancellazione: in fase di esecuzione sono le stesse interfacce).

Inoltre, questo approccio viola il principio di responsabilità singola: la tua classe dovrebbe concentrarsi sull'essere Something (qualunque cosa significhi) e non dovrebbe fare la mappatura su A o B in aggiunta questo compito.

Sembra che tu debba avere un Mapper<Something,A> e un Mapper<Something,B> . In questo modo ogni classe ha una sola responsabilità definita chiaramente e non si incontra il problema di implementare la stessa interfaccia due volte.

    
risposta data 25.11.2013 - 10:17
fonte
0

Dato che non è permesso implementare interfacce multiple, puoi considerare l'uso dell'incapsulamento. (esempio usando java8 +)

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

// TwoMappables.java
public interface TwoMappables {
    default Mappable<A> mapableA() {
         return new MappableA();
    }

    default Mappable<B> mapableB() {
         return new MappableB();
    }

    class MappableA implements Mappable<A> {}
    class MappableB implements Mappable<B> {}
}

// Something.java
public class Something implements TwoMappables {
    // ... business logic ...
    mapableA().mapTo(A);
    mapableB().mapTo(B);
}

Controlla qui per ulteriori informazioni & altri esempi: Come creare una classe Java che implementa un'interfaccia con due tipi generici? .

    
risposta data 07.01.2019 - 16:50
fonte
-1
public interface IMappable<S, T> {
    T MapFrom(S source);
}

// T - target
// S - source

Se vuoi connettere User a UserDTO e mappare User a UserViewModel, avrai bisogno di due implementazioni separate. Non accumulare tutta questa logica in una singola classe: non ha senso farlo.

Aggiornamento per mantenere Joachim felice

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

Ma ora siamo nel regno di Automapper ( link )

    
risposta data 25.11.2013 - 10:35
fonte

Leggi altre domande sui tag