继承,还是我应该使用组合?

时间:2017-12-18 18:47:22

标签: c# .net inheritance polymorphism override

让我说我有一个班级

public class Transfer 
{
    prop1
    prop2
    ....
    public List<SubTransfer> SubTransfers { get; set; }
}

我从连接到数据库的函数中获取

现在我希望有一个类可以为Transfer和SubTransfer中的每一个添加状态。

一个问题是我是否应该在这里使用继承?还是作文?

我认为继承,所以我试图做这样的事情:

public ExtendedSubTransfer : SubTransfer
{
    public StatusEnum Status { get; set; }
}

public ExtendedTransfer : Transfer
{
    public StatusEnum Status { get; set;}
}

我的问题是我不知道如何使用ExtendedTransfer获取ExtendedSubTransfer列表。

我知道我可以使用关键字new覆盖SubTransfers,如下所示:

public new List<ExtendedSubTransfers> SubTransfers {get; set;}

它是“合法的”吗?或者您有其他建议吗?

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

它会编译,但它可能不会做你想要的。请注意,List<ExtendedSubTransfer>不会延伸List<SubTransfer>。例如,如果您有任何使用基类的操作,您将无法获得所需的操作。为了演示,让我们假装基类有一个ID,你想要打印ID。

public void PrintIds()
{
    ExtendedTransfer extendedTransfer = _database.GetExtendedTransfer(...);
    PrintSubTransferIds(extendedTransfer);
}

private PrintSubTransferIds(Transfer transfer)
{
    foreach(var subTransfer in transfer.SubTransfers)
    {
        Console.WriteLine(subTransfer.Id);
    }
}

除非您在从数据库加载项目时做一些非常奇怪的事情,否则上述方法将无效。例如,如果您的加载代码看起来像......

public GetExtendedTransfer(...)
{
    ExtendedTransfer result = new ExtendedTransfer();
    List<ExtendedSubTransfer> subTransfers = _connection.QueryForSubTransfers(...);
    result.SubTransfers = subTransfers;
    return result;
}

然后它将无法正常工作。它不会打印任何子转移ID,因为transfer.SubTransfers将是一个空列表。相反,当您从数据库加载时,您必须做一些奇怪的事情......

public GetExtendedTransfer(...)
{
    ExtendedTransfer result = new ExtendedTransfer();
    List<ExtendedSubTransfer> subTransfers = _connection.QueryForSubTransfers(...);
    result.SubTransfers = subTransfers;
    Transfer subtypedResult = result;
    subtypedResult.SubTransfers = subTransfers.Cast<SubTransfer>();
    return result;
}

此外,以下情况将是编译时错误:

public void PrintIds()
{
    ExtendedTransfer extendedTransfer = _database.GetExtendedTransfer(...);
    PrintSubTransferIds(extendedTransfer.SubTransfers);
}

private PrintSubTransferIds(List<SubTransfer> subTransfers)
{
    foreach(var subTransfer in subTransfers)
    {
        Console.WriteLine(subTransfer.Id);
    }
}

这将无法编译,因为extendedTransfer.SubTransfers类型为List<ExtendedSubTransfer>,无法分配给List<SubTransfer>

更新:那你该怎么做?

C#(4.X及以上)允许covariance上的certain interfaces,例如IReadOnlyList(C#4.5及以上)。这样你就可以......

public class Transfer 
{
    public virtual IReadOnlyList<SubTransfer> SubTransfers { get; private set; }
    public void SetSubTransfers(List<SubTransfer> subTransfers)
    {
        SubTransfers = subTransfers;
    }
}

public class ExtendedTransfer
{
    private List<ExtendedSubTransfer> _subTransfers;

    public override IReadOnlyList<SubTransfer> SubTransfers
    {
        get { return _subTransfers; }
    }

    public void SetSubTransfers(List<ExtendedSubTransfer> subTransfers)
    {
        _subTransfers = subTransfers;
    }
}

这是我解决问题的最佳尝试。但是,您没有提到如何从数据库中获取实体。我不认为EntityFramework默认会对此字段安排感到非常满意。