Programming against interfaces is an often-heard good practice in software development. Together with extension methods, this provides a great functionality. However, in C#, there are limitations to that. Let's declare a simple interface for a 3D-Point:
public interface IPoint3D
{
double X { get; }
double Y { get; }
double Z { get; }
}
I can add extension methods for this point in a static class, for example:
public static class Point3DExtensions
{
public static double SumOfCoordinates(this IPoint3D point)
{
return point.X + point.Y + point.Z;
}
}
However, what I can not code is functionality which returns an instance of the interface itself, like for example:
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);
}
}
The problem here is the part new IPoint3D
, because I can't create an instance of an interface (it's just a contract, not an implementation).
As a workaround, I'd see two possibilites:
In the same assembly as the interface, create an internal class implementing the interface, for example:
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;
}
}
This class won't be seen from outside the assembly, but now, my extension method Add
can still have IPoint3D
as return type, but actually return an instance of SimplePoint
. Noone from outside of the assembly will be able to cast the returned instance to SimplePoint
, and doesn't need to.
The second option would be to add something like a Create
-Method to the interface:
IPoint3D Create(double x, double y, double z);
However, this method is not static, so I would have to invoke it from any instance of IPoint3D
, which is kind of weird, and I don't always have such an instance. The problem here is that static methods are not allowed for interfaces in C#. If they were, one could simply add static IPoint3D Create(double x, double y, double z);
or even something like new(double x, double y, double z);
(for a constructor) to the interface, and use that for object creation.
Now, the actual questions:
- Am I trying to misuse interfaces here?
- Did I miss any possibility to get the desired behaviour?
- Which languages would offer this desired functionality?
Side Note: What I would like to have is e.g. an extension method for classes implementing an interface ICircle3D
, which can calculate a number of points IPoint3D
on those circles.
new
operator for an argument.new
constraint requires a parameterless constructor. Good for general value types, but bad for this sort of immutable class design unfortunately. I expect that this is awkward in most languages, and is avoided by not interfacing things like this that are not ever going to get different implementations.Circle
-Classes in different assemblies, which we do not want to merge at this point, but we would still like to be able to calculate points on all those circles... Reasons for not merging are that they offer a lot of different functions, and we don't want to clutter each other's classes... (However, the extension methods kind of do that, too, but in another place).