所以,请考虑以下情况
我有一个类型为“Shapes”的超类和继承Shapes的类“Box”,“Circle”和“Arrow”。我有一个其他形状的列表,可以包含任何这些类型的成员。我需要通过列表进行枚举并绘制出每个形状。问题是每个形状的绘制方式不同,因此我有:
void Draw(Box b) {}
void Draw(Square s) {}
void Draw(Circle c) {}
问题在于,当我通过列表枚举时,返回的每个元素都是Shape类型(因为列表的类型为Shape),即使它的实际类型可能是Box。因此,没有任何过载被认为是正确的。
我有一个想法是创建一个临时对象并声明它是list元素的实际类型。因此,假设list [i]是Circle类型
object o = Type.GetType(Convert.ToString(list[i].GetType()));
o = list[i];
但是这仍然不起作用,因为现在编译器将'o'的类型识别为Object而不是Circle!
如何解决这个问题?
答案 0 :(得分:8)
在Draw
类中创建一个抽象的Shape
方法。在每个派生类中重写它。让特定的形状吸引自己。
示例:
public interface IDrawingSurface {
// All your favorite graphics primitives
}
public abstract class Shape {
public abstract void Draw();
protected IDrawingSurface Surface {get;set;}
public Shape(IDrawingSurface surface) {
Surface = surface;
}
}
public class Box {
public Box(IDrawingSurface surface) : base(surface) {}
public virtual void Draw(){ Surface.Something();... }
}
public class Square {
public Square(IDrawingSurface surface) : base(surface) {}
public virtual void Draw(){ Surface.Something();... }
}
public class Circle {
public Circle(IDrawingSurface surface) : base(surface) {}
public virtual void Draw(){ Surface.Something();... }
}
答案 1 :(得分:1)
更好的解决方案是在形状abstract
上设置Draw()
函数,然后在Box,Circle和Sqaure中覆盖该函数。
答案 2 :(得分:1)
为什么不在Shapes上绘制虚拟方法然后在每个派生类上覆盖它?然后你可以这样做:
List<Shapes> shapes = ... get your list of shapes somewhere ...
foreach (var shape in shapes) {
shape.Draw();
}
将在特定的派生类上调用正确的虚方法。这是多态性的教科书案例。
答案 3 :(得分:1)
我个人会按照建议亲自使用界面,但是如果您无权访问谁正在呼叫您(例如第三方.dll),那么您可以接受类型为object的参数:
/// <summary>
/// Draw any type of object if the objec type is supported.
/// Circles, Squares, etc.
/// </summary>
/// <param name="objectToDraw"></param>
public void Draw(object objectToDraw)
{
// get the type of object
string type = objectToDraw.GetType().ToString();
switch(type)
{
case "Circle":
// cast the objectToDraw as a Circle
Circle circle = objectToDraw as Circle;
// if the cast was successful
if (circle != null)
{
// draw the circle
circle.Draw();
}
// required
break;
case "Square":
// cast the object as a square
Square square = objectToDraw as Square;
// if the square exists
if (square != null)
{
// draw the square
square.Draw();
}
// required
break;
default:
// raise an error
throw new Exception("Object Type Not Supported in Draw method");
}
}
答案 4 :(得分:0)
void Draw(Shapes s)
{
if (s is Circle)
{
Draw((Circle)s);
}
}
等等。
答案 5 :(得分:0)
public interface IShape
{
public void Draw();
}
public class Circle : IShape
{
public void Draw()
{
do somethig shape specific
}
}
List<IShape> shapes
foreach (IShape shape in shapes)
{
shape.Draw();
}
答案 6 :(得分:0)
void Draw(Box b) {}
是绘制Box类的错误方法。 Box类应该只有Draw()方法。
如果要使用类型形状列表进行绘图,则必须确保在派生类中重写了Draw方法。
您标记为已接受的答案会详细说明。
同样对于信息,Draw(框b)适合静态方法类别。