开发者

How can interfaces implement progressively more-strict typed properties?

I'm working on a series of data structures. Some require a specific number of dimensions (like quad-trees or oct-trees) and some allow for any number (such as kd-trees). I'd like to implement my different structures and interfaces as follows:

public struct Point : IPoint // An n-dimensional point
public struct Point2D : IPoint // A 2-dimensional point

public interface IPointEntity
{
    IPoint Location { 开发者_如何学编程get; }
}
public interface IPointEntity2D : IPointEntity
{
    Point2D Location { get; }
}

This way, I can create classes like this:

public class Quadtree
{
    public void Add(IPointEntity2D value) {...}
}

public class KdTree
{
    public void Add(IPointEntity value) {...}
}

However, I'm told that IPointEntity2D must declare Location as New since it hides IPointEntity.Location. This defeats the purpose, though, as I would have to implement them both separately. It seems to me that the 2D implementation should fulfill the n-D interface's requirement. How can I accomplish this?


EDIT: I've now got it implemented as per Jon Skeet's suggestion:

public struct Point : IPoint // An n-dimensional point
public struct Point2D : IPoint // A 2-dimensional point

public interface IPointEntity<T> where T : IPoint
{
    T Location { get; }
}

public class Quadtree<T> where T : IPointEntity<Point2D>
{
    public void Add(T value) {...}
}

public class KdTree<T> where T : IPointEntity<IPoint>
{
    public void Add(T value) {...}
}

But when I try to make an entity, I can't use them in both appropriate classes, like I had hoped:

public class Sprite2D : IPointEntity<Point2D>
{
    public Point2D Location { get; set; }
}
public class Sprite3D : IPointEntity<Point3D>
{
    public Point3D Location { get; set; }
}

static void Main(string[] args)
{
    var quadtree = new Quadtree<Sprite2D>(); // Works just great
    var kdTree2D = new KdTree<Sprite2D>();   // Doesn't work
    var kdTree3D = new KdTree<Sprite3D>();   // Doesn't work
}


You're looking for covariant return types - they just don't exist in .NET. You have to implement the two properties separately, using explicit interface implementation to avoid them clashing.

One potential workaround is to use a generic interface instead:

public interface IPointEntity<T> where T : IPoint
{
    T Location { get; }
}

Note that this would also allow a class to implement IPointEntity<Point> and avoid boxing a Point into an IPoint when it's accessed.


You could use a generic interface

public interface IPointEntity<T> where T : IPoint 
{
    T Location { get; }
}

and let IPointEntity2D inherit IPointEntity<Point2D>.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜