2011-05-09 52 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