2014-01-25 76 views
0
public abstract class Shape 
{ 
    public String toString() 
    { 
     // ... 
     return ""; 
    } 
} 

public class Rectangle : Shape 
{ 
    public Double width { get; set; } 
    public Double height { get; set; } 
} 

假設我從Rectangle類創建了一個對象。有沒有辦法通過創建的對象寫入Rectangle類對象的屬性值,而不必重寫toString()方法?從基類獲取子類屬性


編輯:

其實我的目的是創建所有子類的通用ToString()方法。

我修改我的代碼

public abstract class Shape 
{ 
    public virtual String ToString(Shape shape) 
    { 
     String result = String.Empty; 

     foreach (var property in shape.GetType().GetProperties()) 
     { 
      result += property.Name + " : " + property.GetValue(shape, null) + "\n"; 
     } 

     return result; 
    } 
} 



    public class Rectangle : Shape, IRectangle 
    { 
     public Double width { get; set; } 
     public Double height { get; set; } 

     public override String ToString() 
     { 
      return base.ToString(this); 
     } 
    } 

結果:

width : 0 
height : 0 

但現在,我必須重寫ToString()方法爲所有子類。我無法找到此代碼複製的解決方案

+0

「寫Recatangle類對象的屬性...」我不確定我跟隨。 –

+1

不,這是不可能的,因爲基類沒有任何關於派生類的知識。 –

+0

坦率地說,以其他方式做更多的工作。 –

回答

0

您不想訪問基類中的派生類,因爲那樣您必須爲您創建的每個派生更新基類。

如果你確定你不想只覆蓋ToString()(並且你很好解釋爲什麼不行,因爲這種方法在這種情況下最有意義),你可以做這樣的事情:

public abstract class Shape 
{ 
    public String toString() 
    { 
     return ShapePrinter.GetString(this); 
    } 
} 

public static class ShapePrinter 
{ 
    public static string GetString(Shape shape) 
    { 
     if (shape is Rectangle) 
     { 
      return GetRectangleString(shape as Rectangle); 
     }  
     if (shape is Circle) 
     { 
      return GetCircleString(shape as Circle); 
     } 

     throw new ArgumentException("shape"); 

    } 

    private static string GetRectangleString(Rectangle rectangle) 
    { 
     return string.Format("Rectangle: {0} x {1}", 
           rectangle.Width, rectangle.Height); 
    } 

    private static string GetCircleString(Circle circle) 
    { 
     return string.Format("Circle: radius {0}", circle.Radius); 
    } 
} 

但後來你幾乎構建一個窮人的實施,你仍然要保持爲每次添加類型的虛擬方法。這與使用override ToString()可以完成的完全相同,因此您必須有令人信服的理由才能使用該功能。

+0

與每次創建新派生類型時必須更新基類有什麼不同? – dcastro

+0

您仍然需要更新它,但它在一個單獨的類中。就像我所說的,你不想知道你的基類是什麼類型實現你的基類。 – CodeCaster

+1

您不希望您的基類知道派生類*,因爲*然後您必須更新它。出於同樣的原因,你不希望任何*類知道類型的派生類型。所有這一切都由LSP解釋 - ShapePrinter不能保證適用於從'Shape'派生的所有*類型。不幸的是,這是Occam的剃刀情況:正確的方法是最簡單的方法 - 讓每個派生類型都覆蓋ToString。 – dcastro

2

如果你只需要保持toString方法,你可以不喜歡它

public abstract class Shape 
{ 
    public String toString() 
    { 
     return InternalToString(); 
    } 

    protected abstract string InternalToString(); 
} 

public class Rectangle : Shape 
{ 
    public Double width { get; set; } 
    public Double height { get; set; } 

    protected override string InternalToString() 
    { 
     return width.ToString() + ", " + height.ToString(); 
    } 
}