2011-11-30 18 views
0

所以,請考慮以下情況發送實際的對象類型重載函數

我有一個超類類型的「形狀」和類「盒子」,「圓」和「箭」繼承形狀。我有其他地方的形狀列表,可以包含任何這些類型的成員。我需要列舉整個列表並繪出每個形狀。的問題是,每個形狀繪製不同的,因此我有:

void Draw(Box b) {} 

void Draw(Square s) {} 

void Draw(Circle c) {} 

的問題是,當我通過列表枚舉,每個元件返回的類型爲形狀的(因爲該列表類型形狀的),即使盡管它的實際類型可能是Box。由於這個原因,沒有一個過載被認爲是正確的。

想到我有一個想法是創建一個臨時對象,並聲明它的實際類型的列表元素。所以,讓我們假設列表[i]是該型圈

object o = Type.GetType(Convert.ToString(list[i].GetType())); 
o = list[i]; 

,但是這仍然因爲現在編譯器識別「O」的類型爲對象,而不是圈不工作!

我該如何解決這個問題?

回答

8

Shape類中創建一個抽象Draw方法。在每個派生類中重寫它。讓特定的形狀畫出自己。


實施例:

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。或者使用一個接口,比如'IDrawable',並且可以繪製子類來實現這個接口。 –

+0

這是我的第二個想法,它肯定會工作。我的寵物與此有關的是,我創建的任何控件都必須傳遞給pictureBox的引用來繪製。我希望能有辦法擺脫它。 – Rishi

+0

將PictureBox概括爲一個'IDrawingSurface'接口,至少你不會依賴於特定的繪圖技術。您也可以將該接口傳遞給形狀的構造函數,以便它不需要在每個「Draw」調用中傳遞。由其他形狀組成的形狀可以將它自己的'IDrawingSurface'引用傳遞給組件形狀,比如說「繪製到我繪製的相同位置」。 –

0
void Draw(Shapes s) 
{ 
    if (s is Circle) 
    { 
     Draw((Circle)s); 
    } 
} 

等等。

+0

雖然你可以做到這一點,但它比我在我之前的回答中提出的虛擬方法方法要昂貴得多。您在這裏採用的方法需要反思才能發送到正確的方法,這會很慢。 –

+0

當然,但如果OP不想改變他的形狀,它的另一種方法。 –

+0

謝謝,這絕對是一個解決方案,但我正在避免必須通過if-else梯形圖來找出對象的實際類型。我覺得它有點否定了多態的整點,不是嗎? – Rishi

1

一個更好的解決辦法是對形狀Draw()一個abstract函數,然後覆蓋盒子,圓和Sqaure該功能。

1

爲什麼不在Draw上繪製虛擬方法,然後在每個派生類上重寫它?那麼你可以這樣做:

List<Shapes> shapes = ... get your list of shapes somewhere ... 

foreach (var shape in shapes) { 
    shape.Draw(); 
} 

將在特定派生類上調用正確的虛方法。這是多態性的教科書案例。

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(); 
} 
1

我會親自使用接口的建議,但如果你沒有訪問是誰給你打電話(如第三方.dll文件),那麼你可以接受的對象類型的參數:

/// <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"); 
     } 
    } 
0
void Draw(Box b) {} 

是繪畫對Box類錯誤的方式。 Box類應該只有Draw()方法。

如果你想使用List類型形狀來繪圖,那麼你必須確保你在派生類中有Draw方法重載。

您標記爲已接受的答案會詳細說明。

對於信息,繪製(框b)適合靜態方法類別。

相關問題