2011-04-27 68 views
2

我正在研究一系列数据结构。一些需要特定数量的维度(如四叉树或八叉树),一些则允许任意数量(如kd-trees)。我想实现我的不同结构和接口如下:然而接口如何实现更严格的类型属性?

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

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

,有人告诉我IPointEntity2D必须声明Location为:

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

这样一来,我可以这样创建类New因为它隐藏了IPointEntity.Location。但是,这个目标失败了,因为我不得不分别实施它们。在我看来,2D实现应该满足n-D接口的要求。我怎样才能做到这一点?


编辑: 现在我找到了实现为每乔恩斯基特的建议:

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) {...} 
} 

但是当我尝试做一个实体,我不能在这两个适当使用它们类,就像我希望的那样:

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 
} 
+0

您没有显示如何声明'Sprite2D'和'Sprite3D'声明。 – 2011-04-27 08:53:08

+0

@Jon - 对不起。他们真的没什么太多。有没有办法让他们在所有适用的结构中工作? – dlras2 2011-04-27 09:27:32

+1

你可以用* 2 *类型参数声明KdTree:'class KdTree 其中TEntity:IPointEntity 其中TPoint:IPoint' – 2011-04-27 09:39:17

回答

4

您正在寻找covariant返回类型 - 它们在.NET中不存在。您必须单独实施这两个属性,使用明确的接口实现来避免它们发生冲突。

一个潜在的解决方法是使用,而不是一个通用的接口:

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

请注意,这将允许一个类来实现IPointEntity<Point>,避免冲拳PointIPoint当它访问。

+0

这解决了我的一些问题。更重要的是,虽然(也许我的问题没有说得太好),但我希望同一个类在特定维度和非特定维度都可用。我会在上面编辑我的帖子。 – dlras2 2011-04-27 08:32:49

1

你可以使用一个通用接口

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

,让IPointEntity2D继承IPointEntity<Point2D>

+1

不用了,它的NoCanDo有两个接口,每个接口都有一个'Location'属性,但是我在写同一个想法的时候大多和你一样:)我不认为在那个时候IPointEntity2D有任何需要,尽管...只需使用'IPointEntity '代替。 – 2011-04-27 06:42:33