Costanti polimorfiche in Java

1

Sto progettando un codice polimorfico per eseguire operazioni matematiche. L'idea è di astrarre la rappresentazione sottostante dei dati, poiché i diversi casi d'uso richiedono rappresentazioni differenti. Le operazioni possono essere eseguite solo con dati dello stesso tipo.

Ci sono molti algoritmi che operano su queste cose e poiché questi algoritmi richiedono molte operazioni. Pertanto, il miglior design di IMO è quello di creare un'interfaccia di base che definisca le operazioni polimorfiche e che ogni tipo di dati sia un'implementazione di tale interfaccia:

interface Datum<D extends Datum<D>> {
    D fuzz();
    D fuse(D that);
    D fizz(int base);
}

class MadDatum extends Datum<BigDatum> {
    ...
}

Tuttavia, ho bisogno anche di determinate costanti per essere definite per ogni rappresentazione. Vorrei accedere a queste costanti in modo polimorfico in modo che gli algoritmi generici che sono agnostici all'implementazione di Datum possano ottenere in modo pulito costanti del tipo corretto. Poiché le costanti non dipendono da Datum , non ha senso definirle come metodi lì. Ma l'unica alternativa ragionevole che posso pensare è creare una gerarchia di tipi paralleli che rappresenta il tipo di dati:

interface DataType<D extends Datum<D>> {
    D warpTorsion();
    D meltingAngle();
}

Ma allora i metodi devono prendere sia il tipo che i dati:

<D extends Datum<D>> D newmansMethod(DataType<D> type, Collection<D> data);

Questo design è scomodo perché duplica la gerarchia delle classi in un modo che il compilatore non controlla - si può facilmente implementare i dati e si dimentica di implementare un DataType corrispondente - e richiede un parametro di metodo aggiuntivo in possibilmente centinaia di metodi.

Sono consapevole che Haskell ammette un'elegante soluzione a questo problema perché consente di specificare le costanti / "funzioni null" nelle classi di tipi. Qualcuno sa un modo pulito per replicare questa funzionalità in Java?

    
posta Solomonoff's Secret 08.06.2016 - 19:32
fonte

2 risposte

2

Se ho capito correttamente la tua domanda, stai cercando abstract static . Questo non è possibile in Java, ma qui ci sono alcuni accorgimenti: link . In alternativa, puoi usare altri linguaggi con questo, ad esempio Scala

    
risposta data 08.06.2016 - 21:20
fonte
1

Potresti andare fino in fondo con lo stile Haskell (le implementazioni di Haskell possono, nel caso più generale, far passare un argomento invisibile per ogni requisito di classe).

Elimina il tipo di base Datum e sposta tutti i metodi interessanti ad esso relativi su DataType :

interface DataType<D> {
    D fuzz(D datum);
    D fuse(D datum1, D datum2);
    D fizz(D datum, int base);
    D warpTorsion();
    D meltingAngle();
}

Quindi ottieni:

<D> D newmansMethod(DataType<D> type, Collection<D> data);

E poiché quasi tutto è interessante nell'implementazione di DataType , è molto difficile dimenticare di implementarlo. Potresti anche aggiornare i tipi esistenti ignoranti della tua libreria con le loro implementazioni di DataType .

Il JITer potrebbe essere in grado di velocizzare le cose perché può dedurre di più sui metodi che verranno chiamati perché tutto il dispatch del metodo è fuori dallo stesso oggetto DataType , ma non so se questo farà la differenza in pratica.

    
risposta data 07.09.2016 - 00:27
fonte