将实际对象类型发送到重载函数

时间:2011-11-30 20:36:44

标签: c# inheritance polymorphism type-conversion

所以,请考虑以下情况

我有一个类型为“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!

如何解决这个问题?

7 个答案:

答案 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)适合静态方法类别。