Объектно-ориентированное программирование Nth Child - PullRequest
0 голосов
/ 09 мая 2011

для конкретного языка (однако, если вам нужен язык, пожалуйста, используйте C ++ / C # или Javascript).Я пытался понять, как мне поступить, и как получить доступ к дочерним объектам из родительского объекта.

Скажем, у меня есть следующие классы, и они не написаны должным образом и т. Д ...:

Класс: roomContainer (контейнер объектов)
Класс: Table (базакласс для таблицы, содержит свойство максимальных мест, текущее количество мест, массив мест)
Класс: Desk (расширяет таблицу, содержит свойство для максимальных розыгрышей, массив розыгрышей)
Класс: seat (базовый класс для сидений, содержит свойство максимальных ножек, подлокотник, спинка)
Класс: couch (расширяет сиденье, добавляет свойство максимум сидений)

Если ясоздайте экземпляр roomContainer и добавьте в его контейнер таблицу couch.Внутри стола я создаю несколько мест (или стульев) и стол.

Как я смогу получить доступ к свойству свойства дочерних объектов, когда родительский объект имеет контейнер различных объектов.Т.е. roomContainer Контейнер объектов, одним из которых является таблица и рабочий стол - где рабочий стол имеет различные свойства и массив рисунков и т. Д.?

Ответы [ 3 ]

1 голос
/ 09 мая 2011

Вы ищете что-то под названием Составной шаблон проектирования . Это позволяет вам вкладывать объекты (как вы описали) и хранить ссылки как на родительский, так и на дочерний (хотя некоторые реализации не поддерживают родительскую ссылку - это необязательно).

Вот пример реализации с использованием вашей схемы:

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 голосов
/ 09 мая 2011

Примерно так:

IEnumerable<Desk> desks = roomContainer.OfType<Desk>();
//Iterate and do stuff.
IEnumerable<Table> tables = roomContainer.OfType<Table>();
//Iterate and do stuff.
0 голосов
/ 09 мая 2011

Если все используют общие методы, например 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(); // ......
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...