Domanda

Ho un certo numero di diverse rappresentazioni dello stesso tipo di oggetto; chiamiamolo una cosa. "Cosa" è un'interfaccia marcatore. ThingFormat0, ThingFormat1, ThingFormat2 ecc, sono tutti i JavaBeans che implementano Thing. (Perché sono JavaBeans, un marshaller JSON li converte automaticamente da e per JSON automaticamente.) ThingFormat1 ha pochi membri come il nome e l'ID. ThingFormat2 ha collegamenti in notazione URI ad altre cose. In ThingFormat3 ha ThingFormat1 rappresentazioni di quelle altre cose, ecc.

Il serializzatore JSON sa come convertire un URI automaticamente. (Funziona per ogni classe in cui è possibile utilizzare toString () e il costruttore di NomeClasse (stringa String) per convertire.)

Voglio avere un ThingFormat0 che si comporta come un URI, ma implementa l'interfaccia Cosa marcatore.

public class ThingFormat0 extends URI implements Thing {}

Questo non funziona perché URI è una classe finale e non può essere sottoclassi.

L'unico modo che posso pensare di farlo è facendo un decoratore (una specie molto degenerata di decoratore in quanto non aggiunge alcuna funzionalità per URI). Questo è facile in alcune lingue "duck-digitato", ma più di un dolore in Java, perché devo avvolgere un URI e implementare tutti i metodi di URI di cui ho bisogno. C'è un modo più semplice?

È stato utile?

Soluzione

Due semplici modi mi viene in mente:

  • Se si utilizza Eclipse, si può avere metodi delegato per ogni campo generato automaticamente.
  • Copiare l'origine di URI in una nuova classe di nome ThingURI.

Altri suggerimenti

C'è qualche motivo la classe non può utilizzare la composizione al posto di eredità?

public class ThingFormat0 implements Thing {
  private final URI uri;

  public ThingFormat0(String uri) { this.uri = URI.create(uri); }

  public ThingFormat0(URI uri) { this.uri = uri; }

  public URI getUri() { return uri; }

  @Override public String toString() {
    return uri.toString();
  }
}

Non si può sottoclasse una classe finale. Periodo.

Nel caso di URI, è quasi certamente finale per motivi di sicurezza; cioè impedire a qualcuno di rottura sicurezza sandbox fornendo un sottotipo subdolo di URI che (per esempio) le permette di sovvertire il controllo di accesso.

Quindi sì, è necessario utilizzare un involucro o decoratore o qualcosa del genere.

// base class that handles delegation
class BaseThing implements Thing {

   BaseThing(String uri) { ... }

   BaseThing(URI uri) { ... }

   URI getURI() { ... }

   ...
}

class ThingFormat0 extends BaseThing {
   ...
}

Si sta trovando questo è difficile, perché i tipi di ThingFormat non sono URI. Espongono URI e possono corrispondere a URI, ma che non li rende URI. Forse stai struggimento per implementazione eredità , ma Interfaccia eredità fallisce qui perché questa non è una vera e propria è-un rapporto; fallisce il LSP .

Si consideri, ad esempio, se un ThingFormat ha uno schema o di un componente frammento, o se uno può essere risolto nei confronti di alcuni URI di base. Quelle sono le sfaccettature e le operazioni di URI che non hanno molto a che fare con ThingFormat, qualunque cosa succede a fare.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top