面向对象编程第 n 个孩子
本文关键字:孩子 面向对象编程 | 更新日期: 2023-09-27 17:55:48
特定于语言(但是,如果您需要一种语言,请使用C++/C#或Javascript)。我试图弄清楚我将如何做到这一点,以及如何从父对象访问子对象。
假设我有以下类,这些类没有正确编写等:
类:roomContainer
(对象的容器)
类:Table
(表的基类,包含最大席位数、当前席位数、席位数组的属性)
类:Desk
(扩展表,包含最大绘制的属性,绘制数组)
等级:seat
(座椅的基本等级,包含最大腿,扶手,靠背的属性)
舱位:couch
(延长座位,增加酒店最大座位数)
如果我创建一个roomContainer
实例,并在它的容器中添加一个表,沙发。在桌子上,我创造了多个座位(或椅子)和一张桌子。
当父对象具有不同对象的容器时,我将如何能够访问子对象属性的属性。即对象的roomContainer
容器,其中一个是桌子和桌子 - 其中桌子具有不同的属性和绘制数组等。 ?
您正在寻找一种称为复合设计模式的东西。 这允许您嵌套对象(如您所描述的),并保存对父项和子项的引用(尽管某些实现不维护父引用 - 这是可选的)。
下面是使用架构的示例实现:
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.