c父-子设计
本文关键字: | 更新日期: 2023-09-27 18:08:43
我正在设计一个c#类,想知道我的设计是否正确。
abstract class PersonBase
{
public string Name { get; set; }
public PersonBase Parent { get; set; }
public List<PersonBase> Children { get; set; }
}
class Person : PersonBase
{
//public override List<Person> Children { get; set; }
public Person()
{
Children = new List<PersonBase>();
}
public void Add(Person child)
{
child.Parent = this;
Children.Add(child);
}
}
测试代码:
private void button1_Click(object sender, EventArgs e)
{
Person parent = new Person();
parent.Name = "parent";
Person child = new Person();
child.Name = "child1";
child.Add(new Person() { Name = "grandchild1" });
parent.Add(child);
}
它按预期工作。我可以从层次结构中的任何位置访问父子对象。我担心的是它看起来是递归或循环引用(在这里找不到正确的单词(。
以下是我最后所做的:
public class Person
{
public string Name { get; set; }
public Person Parent { get; set; }
public List<Person> Children { get; private set; }
public Person()
{
Children = new List<Person>();
}
public void AddChild(Person child)
{
if (child == this) { return; }
if (Children.Contains(child)) { return; }
child.Parent = this;
Children.Add(child);
}
}
Like@LukeH要求你脱离BasePerson和Person是没有意义的。这会很好用的。
public class Person
{
public string Name { get; set; }
public Person Parent { get; set; }
public IList<Person> Children { get; private set; }
public Person()
{
Children = new List<Person>();
}
public void Add(Person child)
{
child.Parent = this;
Children.Add(child);
}
}
如果你要有不同类型的Person,那么如果没有继承的逻辑,你可能想把你的东西分解成Interface,如果你想提供一些默认逻辑,你可以把它分解成抽象类。
编辑:添加Danny 中表达的问题
如果您使用child,它可能会成为一个问题。添加(Me或MyParent或祖先(。那么,这将是一个无休止的参考循环。您可能希望在add方法中添加代码,以防止不正确的使用,这样"Person"就不能将自己或其父母添加为子对象。
基类是多余的,而且,您假设子类不是null并在构造函数中赋值,但它有一个公共setter。
将children的setter更改为private或protected,不必担心循环引用——只需用属性标记parent属性,即可防止其序列化。
//Declare and initialize Person a, b, c;
a.Add(c);
b.Add(c); // Now a thinks c is a child, but c does not think a is a parent!
您需要某种验证,也许c还没有父级,或者只在parent.CreateChild方法中设置父级/子级。或者允许它有多个父母。
(此外,我会声明AddChild方法,因为它就是这么做的。同时也要注意其他评论者的设计考虑因素。(
也许是这样:
class Person
{
public string Name { get; private set; }
public Person Parent { get; private set; }
public IList<Person> Children { get; private set; }
private Person() {} // Private constructor
public static Person CreatePersonNoParent(string name){*implementation elided*};
public Person CreateChild(string name)
{
Person child = new Person { Name=name, Parent=this };
this.Children.Add(child);
return child;
}
}