Question

J'ai un certain nombre de différentes représentations du même genre d'objet; Appelons une chose. « Chose » est une interface de marqueur. ThingFormat0, ThingFormat1, ThingFormat2 etc. sont tous JavaBeans qui mettent en œuvre chose. (Parce qu'ils sont JavaBeans, un placier JSON les convertit automatiquement et de JSON automatiquement.) ThingFormat1 a quelques membres comme le nom et id. ThingFormat2 a des liens URI vers d'autres choses. Dans ThingFormat3 a ThingFormat1 représentations de ces autres choses, etc.

Le sérialiseur JSON sait comment convertir automatiquement un URI. (Il fonctionne pour toutes les classes où vous pouvez utiliser toString () et le constructeur ClassName (string String) pour convertir.)

Je veux avoir un ThingFormat0 qui se comporte comme un URI, mais fait la chose d'interface marqueur.

public class ThingFormat0 extends URI implements Thing {}

Cela ne fonctionne pas parce que URI est une classe finale et ne peut pas être sous-.

La seule façon que je peux penser à le faire est en faisant un décorateur (une sorte très dégénérée de décorateur car il n'ajoute aucune fonctionnalité à l'URI). Ceci est facile dans certains « typé canard » langues, mais plus d'une douleur en Java, parce que je dois conclure un URI et mettre en œuvre toutes les méthodes d'URI que j'ai besoin. Y at-il un moyen plus facile?

Était-ce utile?

La solution

Deux façons simples que je peux penser:

  • Si vous utilisez Eclipse, vous pouvez avoir des méthodes de délégué pour tout champ généré automatiquement.
  • Copier la source d'URI dans une nouvelle classe nommée ThingURI.

Autres conseils

Y at-il raison de la classe ne peut pas utiliser la composition au lieu de l'héritage?

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();
  }
}

Vous ne pouvez pas sous-classe d'une classe finale. Période.

Dans le cas d'URI, il est presque certainement dernière pour des raisons de sécurité; à-dire pour empêcher quelqu'un de casser la sécurité sandbox en fournissant un sous-type sournoise d'URI (par exemple) lui permet de subvertir le contrôle d'accès.

Alors oui, vous aurez besoin d'utiliser un emballage ou décorateur ou quelque chose comme ça.

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

   BaseThing(String uri) { ... }

   BaseThing(URI uri) { ... }

   URI getURI() { ... }

   ...
}

class ThingFormat0 extends BaseThing {
   ...
}

Vous trouvez cela est difficile parce que vos types de ThingFormat ne sont pas URIs. Ils exposent et URIs peuvent correspondre à des URIs, mais cela ne les rend pas URIs. Peut-être vous languir pour l'héritage d'implémentation , mais l'héritage d'interface échoue ici parce que ce n'est pas un bon est-une relation ; il échoue LSP .

Prenons, par exemple, si un ThingFormat dispose d'un système ou d'un composant fragment, ou si l'on peut être résolu contre une URI de base. Ce sont des facettes et des opérations de URIs qui n'ont pas grand-chose à voir avec ThingFormat, tout ce qu'il arrive à faire.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top