使用父对象的值扩展对象

本文关键字:对象 扩展 | 更新日期: 2023-09-27 18:00:20

假设我有一个类:

public class Parent
{
    public string Name { get; set; }
    public string City { get; set; }
}

在某个函数中,我得到了Parent类型的对象列表,接下来我想用一些值的新字段来扩展这些对象,所以我声明了一个扩展类,如下所示:

public class Child : Parent
{
    public Child(Parent parent)
    {
        Name = parent.Name;
        City = parent.City;
    }
    public int Age { get; set; }
}

并为每个扩展对象调用costructor。有更好的方法吗?如果Parent中将有多个属性,该怎么办?也许还有更优雅的方法可以实现这一点?

使用父对象的值扩展对象

我想您可能正在寻找一个复制构造函数模式。每个级别定义一个protected构造函数,该构造函数复制相关属性:

public class Parent
{
    public string Name { get; set; }
    public string City { get; set; }
    //normal constructor
    public Parent()
    {
    }
    protected Parent(Parent copy)
    {
        this.Name = copy.Name;
        this.City = copy.City;
    }
}

Child将从Parent继承,向下传递到复制构造函数,然后根据需要附加其新值:

public class Child : Parent
{
    public string NewInfo { get; set; }
    public Child(Parent copy)
        : base(copy)
    {
    }
}

用法可能看起来像:

Parent parent = new Parent() { Name = "Name", City = "StackOverflow"};
Child child = new Child(parent) { NewInfo = "Something new!" };
Console.WriteLine(child.Name); //Name
Console.WriteLine(child.City); //StackOverflow
Console.WriteLine(child.NewInfo); //Something new!

这样做的好处是,您可以拥有多个级别的继承,每个级别都管理自己的属性。

编辑:给出你最近的评论:

这个问题的动机是在我得到包含数据的对象列表,并且希望显示此数据,但包含一些附加字段,而不涉及基类。

也许更好的方法是包装基类:

public class Child
{
    private readonly Parent WrappedParent;
    public string NewInfo { get; set; }
    public string Name 
    { 
        get { return WrappedParent.Name; }
        set { WrappedParent.Name = value; }
    }
    public string City 
    { 
        get { return WrappedParent.City; }
        set { WrappedParent.City = value; }
    }
    public Child(Parent wrappedParent)
    {
        this.WrappedParent = wrappedParent; 
    }
}

不利的一面是,您必须重新声明每个属性,并且您不再继承(不能被视为)"Parent",但之后您就明确地"不再接触"基类了。如果对您更好的话,可以将"Parent"属性移动到IParent接口中,但再次这样做会"触及"基类,因为您必须将IParent接口声明添加到其类定义中。

不确定我是否弄错了,但这可能是一个更标准的解决方案

public class Parent
{
    public Parent(string name, string city)
    {
       Name = name;
       City = city;
    }
    public string Name { get; set; }
    public string City { get; set; }
}
public class Child : Parent
{
    public Child(string name, string city, int age) : base(name, city)
    {
       Age = age;
    }
    public int Age { get; set; }
} 

您可以执行此

public class Parent
{
    public string Name { get; set; }
    public string City { get; set; }
    public Parent(string name, string city)
    {
        this.Name = name;
        this.City = city;
    }
    public Parent():this(string.Empty, string.Empty)
    {
    }
}
public class Child : Parent
{
    public Child(Parent parent, int age):base(parent.Name, parent.City)
    {
        this.Age = age;
    }
    public int Age { get; set; }
}

在Visual Studio的最新版本(VS Community Edition 2019)中,我能够键入以下内容:

internal class Child : IParent
{
    private IParent parent;
    public ChildField childField;
    public Child(IParent parent, ChildField newChildField)
    {
        this.parent = parent;
        this.childField = newChildField;
    }
}

然后,我将鼠标悬停在IParent上(由于未完全实现,它显示了一条错误消息),Ctrl。以解决该错误通过父级实现接口";。单击该选项,VS为您键入所有属性和方法,包装基类。简单、正确、棒极了。