通过介绍,我正在为个人学习目的创建一个基本的Quadtree引擎。我希望这个引擎能够处理许多不同类型的形状(目前我正在使用圆形和正方形),它们将在窗口中移动并在发生碰撞时执行某种操作。 / p>
到目前为止,这是我的形状对象:
public class QShape {
public int x { get; set; }
public int y { get; set; }
public string colour { get; set; }
}
public class QCircle : QShape {
public int radius;
public QCircle(int theRadius, int theX, int theY, string theColour) {
this.radius = theRadius;
this.x = theX;
this.y = theY;
this.colour = theColour;
}
}
public class QSquare : QShape {
public int sideLength;
public QSquare(int theSideLength, int theX, int theY, string theColour) {
this.sideLength = theSideLength;
this.x = theX;
this.y = theY;
this.colour = theColour;
}
}
现在我的问题是,我如何在C#中创建一个通用列表(List<T> QObjectList = new List<T>();
),这样我就可以有一个包含所有这些可能具有不同属性的各种形状的列表(例如,QCircle具有“radius”属性虽然QSquare有“sideLength”属性)?实施的一个例子也很有帮助。
我只知道这个问题有一个愚蠢明显的答案,但无论如何我都会感激任何帮助。我想回到C#;它显然已经有一段时间......
答案 0 :(得分:7)
您需要使用向下广播
将对象存储在具有基类
的列表中 List<QShape> shapes = new List<QShape>
如果你知道它是什么,你可以安全地向上翻转对象。
if(shapes[0] is QSquare)
{
QSquare square = (QSquare)shapes[0]
}
您也可以隐式转发对象
QSquare square = new Square(5,0,0,"Blue");
QShape shape = square
For more information read the Upcasting and Downcasting sections here
答案 1 :(得分:3)
您应该实施Interface
。例如
public interface IHasLength
{
int Length;
}
然后在实施中你可以做
public class QSquare : QShape, IHasLength {
public int sideLength;
public QSquare(int theSideLength, int theX, int theY, string theColour) {
this.sideLength = theSideLength;
this.x = theX;
this.y = theY;
this.colour = theColour;
}
public int Length { get { return sideLength; } }
}
public class QCircle : QShape, IHasLength {
public int radius;
public QSquare(int theSideLength, int theX, int theY, string theColour) {
this.sideLength = theSideLength;
this.x = theX;
this.y = theY;
this.colour = theColour;
}
public int Length { get { return radius; } }
}
最后,在您的列表中:
List<IHasLength> shapesWithSomeLength = new List<IHasLength>();
现在,您的列表可以包含实现IHasLength
的任何内容,无论它是QCircle
,QShape
,还是QDuck
,只要它实现{{1} }}
答案 2 :(得分:2)
您可以将它们存储在List<QShape>
中,但这意味着您无法访问特定于类型的属性。
通常,您可以通过在基类中提供公共接口并覆盖子类中的行为来解决此问题。通过这种方式,通用接口可以隐藏各种各样的行为。例如,Grow
方法可以隐藏不同形状的增长项目的复杂性,并且可以在没有明确知道其运行形状的情况下调用。
public abstract class QShape {
public abstract void Grow(int amt);
}
public class QSquare : QShape {
private int sideLength;
public override void Grow(int amt)
{
sideLength+=amt;
}
}
public class QCircle : QShape {
private int radius;
public override void Grow(int amt)
{
radius+=amt;
}
}
答案 3 :(得分:2)
这是你想要的吗?
public class QShape
{
protected QShape() { }
public int x { get; set; }
public int y { get; set; }
public string colour { get; set; }
}
public class QCircle : QShape
{
public int radius;
public QCircle(int theRadius, int theX, int theY, string theColour)
{
this.radius = theRadius;
this.x = theX;
this.y = theY;
this.colour = theColour;
}
}
public class QSquare : QShape
{
public int sideLength;
public QSquare(int theSideLength, int theX, int theY, string theColour)
{
this.sideLength = theSideLength;
this.x = theX;
this.y = theY;
this.colour = theColour;
}
}
class Program
{
static void Main(string[] args)
{
List<QShape> list = new List<QShape>();
list.Add(new QCircle(100, 50, 50, "Red"));
list.Add(new QCircle(100, 400, 400, "Red"));
list.Add(new QSquare(50, 300, 100, "Blue"));
foreach (var item in list.OfType<QCircle>())
{
item.radius += 10;
}
foreach (var item in list.OfType<QSquare>())
{
item.sideLength += 10;
}
}
}
答案 4 :(得分:1)
我觉得我错过了一些东西,但......
List<QCircle> circleObjects = new List<QCircle>();
和
List<QSquare> squareObjects = new List<QSquare>();
将完美运作。
编辑:
啊,我不明白被问到的是什么。是的,因为您的QCircle
和QSquare
类继承自QShape
,您可以这样做。
List<QShape> shapes= new List<QShape>();
值得注意的是,如果您想要访问该列表中所有radius
的{{1}}属性,那么您将不得不根据类型过滤列表。
答案 5 :(得分:1)
您可以使用Ian Mercer的评论List<QShape>
以下是你如何填写它:
List<QShape> shapes = new List<QShape>();
QCircle circle = new QCircle();
shapes.Add(circle);
取消装箱:
QCircle circle = (QCircle) shapes[0];
如果你需要从基类调用一个方法,不需要取消装箱,只需使用它。
答案 6 :(得分:-1)
您已经使用类定义走上了正确的轨道。你需要做的是创建一个超级类List
(在这种情况下,QShape
),它将能够容纳你的所有形状。
以下是如何制作它的示例:
List<QShape> objects = new List<QShape>();
objects.add(new QCircle(...));
objects.add(new QSquare(...));
这里的问题是区分列表中的所有内容。这是通过C#的getType()
和typeof()
方法完成的。 (Jon Skeet has an excellent answer about how to do this)。基本上,它看起来像这样:
if(objects.get(some_position).getType() == typeof(QCircle))
QCircle circle = objects.get(some_position);
else if(/* like above with QSquare */)
QSquare square = objects.get(some_position);
执行此操作后,您可以像平常一样继续使用对象。但是,如果您尝试从列表中访问它们,则只能使用QShape
具有的方法和变量,因为列表中的每个对象都将被强制转换为它。
答案 7 :(得分:-1)
public Class abstract Base<T>
{
public abstract List<T>GetList();
}
然后这样做
public class className:Base<ObjectName>
{
public override List<T>GetList()
{
//do work here
}
}