面向对象编程第 n 个孩子

本文关键字:孩子 面向对象编程 | 更新日期: 2023-09-27 17:55:48

特定于语言(但是,如果您需要一种语言,请使用C++/C#或Javascript)。我试图弄清楚我将如何做到这一点,以及如何从父对象访问子对象。

假设我有以下类,这些类没有正确编写等:

类:roomContainer(对象的容器)
类:Table(表的基类,包含最大席位数、当前席位数、席位数组的属性)
类:Desk(扩展表,包含最大绘制的属性,绘制数组)
等级:seat(座椅的基本等级,包含最大腿,扶手,靠背的属性)
舱位:couch(延长座位,增加酒店最大座位数)

如果我创建一个roomContainer实例,并在它的容器中添加一个表,沙发。在桌子上,我创造了多个座位(或椅子)和一张桌子。

当父对象具有不同对象的容器时,我将如何能够访问子对象属性的属性。即对象的roomContainer容器,其中一个是桌子和桌子 - 其中桌子具有不同的属性和绘制数组等。 ?

面向对象编程第 n 个孩子

您正在寻找一种称为复合设计模式的东西。 这允许您嵌套对象(如您所描述的),并保存对父项和子项的引用(尽管某些实现不维护父引用 - 这是可选的)。

下面是使用架构的示例实现:

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; }
    }
}

如果 all 共享通用方法,例如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(); // ......
    }
}

像这样:

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