2011-05-09 62 views
0

語言特定(但是,如果您需要一種語言,請使用C++/C#或Javascript)。我試圖弄清楚如何去做這件事,以及如何從父對象訪問子對象。面向對象編程Nth子

說我有下面的類,這些都是不正常等書面...:

類:roomContainer(對象的容器)
類:Table(一個表的基類,包含了最大的財產座位數目,座位數目)
類別:Desk(擴展表,包含最大繪製,排列的屬性)
類別:seat(座位的基類,包含最大值,腿,扶手,靠背)
類:couch(擴展座位,增加屬性最大座位)

如果我創建了一個roomContainer的實例,並在其容器中添加一個表,沙發。在桌子內,我創建了多個座位(或椅子)和一張桌子。

當父對象具有不同對象的容器時,我將如何訪問子對象屬性的屬性。即對象的容器,其中一個是桌子和一張桌子 - 桌子上有不同的屬性和一系列繪畫等等。?

回答

0

如果所有的共享方法,例如Render(), Update(), SaveDetails(int Id), LoadDetails(int Id)那麼你可以使它們都從一個基類繼承,或者所有的實現一個通用的接口。這將在調用常用方法(或訪問公共屬性)時刪除對下注的需求。 要訪問派生類的唯一屬性,您需要檢查子對象的類型,然後轉換子對象以訪問該屬性。

編輯:例:

foreach(Object obj in Room.ChildObjects) 
{ 
    if(obj is Desk) 
    { 
     Desk DeskObj = obj as Desk; // Cast the object reference as a desk. 
     DeskObj.MaxDraws = 50; // It's a big desk! 
     DestObj.Draws[1] = new Draw(); // ...... 
    } 
} 
+0

如果他們是不同類型的對象,而且並不總是共享方法(如果他們確實有相同的方法採用不同類型的輸入),我是否需要檢索對象並從容器中對對象進行操作。例如,如果我需要設置繪圖的屬性,我需要去RoomContainer>桌面對象>繪製,有一個方法從數組中找到適當的繪製對象並返回對象。然後,一旦我有對象返回調用它的屬性/方法? – banvan 2011-05-09 10:25:33

+0

@banvan,看我上面的編輯。 – 2011-05-09 10:39:17

1

你正在尋找的東西叫做Composite Design Pattern。這允許你嵌套對象(就像你所描述的那樣),並且持有對父對象和子對象的引用(儘管一些實現沒有維護父引用 - 這是可選的)。

下面是使用你的架構的範例:

public static class Program  // the supporting class definitions are below 
{ 
    public static void Main() 
    { 
     // create a root container 
     var room = new RoomContainer(); 

     // create a child 
     var table = new Table(room, 4); 

     // put the table in the room 
     room.Add(table); 

     MakeMess(room); 
    } 

    // to show you how to access the properties 
    // if you don't already have a reference: 
    public static void MakeMess(RoomContainer room) 
    { 
     if(room == null) 
     { 
      throw new ArgumentNullException("room"); 
     } 
     var seats = room.GetChildren<Table>().First().Seats.ToArray(); 
     for (int index = 0; index < seats.Length; index++) 
     { 
      Console.WriteLine("You have kicked over Seat #{0}",(index+1).ToString()); 
     } 
    } 

} 

// This is the base class of the components and provides the core functionality. 
// You will want to make this object's interface minimal, so that the logic 
// is consistent with all its children (without knowing what they might be in advance) 

public abstract class Component 
{ 

    private readonly IList<Component> _children; 
    private readonly Component _container; 

    protected Component(Component container) 
    { 
     _container = container; 
     _children = new Component[] { }; 
    } 

    public bool IsRoot { get { return _container == null; } } 

    public abstract bool IsContainer { get; } 


    public virtual void Add(Component component) 
    { 
     if (component == null) 
     { 
      throw new ArgumentNullException("component"); 
     } 
     if (!IsContainer) 
     { 
      throw new NotSupportedException("Add is not supported by leaf components"); 
     } 
     _children.Add(component); 
    } 

    public IEnumerable<T> GetChildren<T>() 
     where T: Component 
    { 
     if (!IsContainer) 
     { 
      throw new NotSupportedException("Only containers have children"); 
     } 
     return _children.OfType<T>(); 
    } 

    public IEnumerable<Component> Children 
    { 
     get 
     { 
      if (!IsContainer) 
      { 
       throw new NotSupportedException("Only containers have children"); 
      } 
      return _children; 
     } 
    } 

} 

public class RoomContainer : Component 
{ 
    public RoomContainer() : base(null) 
    { 
    } 

    public override bool IsContainer { get { return true; } } 
} 

public class Table : Component 
{ 
    private readonly int _maximumSeatCount; 

    public Table(Component container, int maximumSeatCount) : base(container) 
    { 
     _maximumSeatCount = maximumSeatCount; 
    } 

    public override bool IsContainer { get { return true; } } 


    protected virtual bool CanAdd(Component component) 
    { 
     return component is Seat && MaximumSeatCount > CurrentSeatCount; 
    } 

    public override void Add(Component component){ 
      if(CanAdd(component)){ 
       base.Add(component); 
      } 
      else 
      { 
       throw new NotSupportedException("The component was an invalid child of Table and could not be added."); 
      } 
     } 

    public int MaximumSeatCount { get { return _maximumSeatCount; } } 
    public int CurrentSeatCount { get { return Seats.Count(); } } 
    public IEnumerable<Seat> Seats { get { return Children.OfType<Seat>(); } } 
} 
public class Seat : Component 
{ 
    // you can restrict the constructor to only accept a valid parent 
    public Seat(Table table) : base(table) 
    { 
    } 

    public override bool IsContainer 
    { 
     get { return false; } 
    } 
} 
0

事情是這樣的:

IEnumerable<Desk> desks = roomContainer.OfType<Desk>(); 
//Iterate and do stuff. 
IEnumerable<Table> tables = roomContainer.OfType<Table>(); 
//Iterate and do stuff. 
+0

這隻有在「RoomContainer」實現IEnumerable時纔有意義 – smartcaveman 2011-05-09 14:06:10