La programmazione contro le interfacce è una buona pratica spesso ascoltata nello sviluppo del software. Insieme ai metodi di estensione, offre una grande funzionalità. Tuttavia, in C #, ci sono dei limiti. Dichiariamo un'interfaccia semplice per un punto 3D:
public interface IPoint3D
{
double X { get; }
double Y { get; }
double Z { get; }
}
Posso aggiungere metodi di estensione per questo punto in una classe statica, ad esempio:
public static class Point3DExtensions
{
public static double SumOfCoordinates(this IPoint3D point)
{
return point.X + point.Y + point.Z;
}
}
Tuttavia, ciò che non posso codificare è la funzionalità che restituisce un'istanza dell'interfaccia stessa, come ad esempio:
public static class Point3DExtensions
{
public static IPoint3D Add(this IPoint3D point1, IPoint3D point2)
{
return new IPoint3D(point1.X + point2.X, point1.Y + point2.Y, point1.Z + point2.Z);
}
}
Il problema qui è la parte new IPoint3D
, perché non riesco a creare un'istanza di un'interfaccia (è solo un contratto, non un'implementazione).
Come soluzione, vedrei due possibilità:
Nello stesso assembly dell'interfaccia, crea una classe interna che implementa l'interfaccia, ad esempio:
internal class SimplePoint : IPoint3D
{
public double X { get; }
public double Y { get; }
public double Z { get; }
public SimplePoint(double x, double y, double z)
{
this.X = x;
this.Y = y;
this.Z = z;
}
}
Questa classe non verrà vista dall'assembly, ma ora il mio metodo di estensione Add
può ancora avere IPoint3D
come tipo restituito, ma in realtà restituisce un'istanza di SimplePoint
. Nessuno dall'esterno dell'assembly sarà in grado di eseguire il cast dell'istanza restituita a SimplePoint
e non è necessario.
La seconda opzione sarebbe quella di aggiungere qualcosa come un Create
-Method all'interfaccia:
IPoint3D Create(double x, double y, double z);
Tuttavia, questo metodo non è statico, quindi dovrei invocarlo da qualsiasi istanza di IPoint3D
, che è un po 'strano, e non ho sempre un'istanza del genere. Il problema qui è che i metodi statici non sono consentiti per le interfacce in C #. Se lo fossero, si potrebbe semplicemente aggiungere static IPoint3D Create(double x, double y, double z);
o anche qualcosa come new(double x, double y, double z);
(per un costruttore) all'interfaccia e usarlo per la creazione dell'oggetto.
Ora, le domande attuali:
- Sto tentando di utilizzare in modo improprio le interfacce qui?
- Mi sono perso ogni possibilità di ottenere il comportamento desiderato?
- Quali lingue offrirebbero questa funzionalità desiderata?
Nota a margine: cosa vorrei avere ad es. un metodo di estensione per le classi che implementano un'interfaccia ICircle3D
, che può calcolare un numero di punti IPoint3D
su quelle cerchie.