当你读到这篇文章时,你会很想给出这样的建议,比如“这是一个坏主意,原因如下……”
请耐心等待。我知道还有其他方法可以解决这个问题。这个问题应该被认为是琐事。
假设您有一个“交易”类,它具有所有交易共有的属性,例如发票、采购订单和销售收据。
让我们以交易“金额”为例,这是给定交易中最重要的货币金额。
public class Transaction
{
public double Amount { get; set; }
public TxnTypeEnum TransactionType { get; set; }
}
此金额在派生类型中可能有更具体的名称……至少在现实世界中是这样。例如,以下值实际上都是同一个东西:
- 交易 - 金额
- 发票 - 小计
- 采购订单 - 总计
- 销售收据 - 金额
所以现在我想要一个派生类“发票”,它有一个小计而不是一般命名的金额。理想情况下,以下两项都为真:
- 在 Transaction 实例中,Amount 属性是可见的。
- 在 Invoice 的实例中,Amount 属性将被隐藏,但 Subtotal 属性将在内部引用它。
发票看起来像这样:
public class Invoice : Transaction
{
new private double? Amount
{
get
{
return base.Amount;
}
set
{
base.Amount = value;
}
}
// This property should hide the generic property "Amount" on Transaction
public double? SubTotal
{
get
{
return Amount;
}
set
{
Amount = value;
}
}
public double RemainingBalance { get; set; }
}
当然,Transaction.Amount 在 Invoice 的任何实例上仍然可见。
感谢您的关注!
最佳答案
感谢所有的帮助。
好的,当派生类是基实例时,当然不能“隐藏”基类的公共(public)属性。在我大脑深处的某个地方,我已经知道了。呸!
我最终通过使用名为 TransactionBase 的第三类,让语法糖按照我希望的方式为消费者服务。此类是抽象的,包含存在于所有交易中的共享的、非别名的内容,例如货币、汇率、创建/修改的日期和时间、交易日期等……除了金额等别名的内容。
在这里,我只显示有问题的 Amount 属性:
public abstract class TransactionBase
{
protected virtual double Amount { get; set; }
}
然后交易看起来像这样:
public class Transaction : TransactionBase
{
public new double Amount
{
get
{
return base.Amount;
}
set
{
base.Amount = value;
}
}
}
和发票:
public class Invoice : TransactionBase
{
public double SubTotal
{
get
{
return Amount;
}
set
{
Amount = value;
}
}
}
并且访问按照我想要的方式工作:
var transaction = new Transaction();
// This line works fine:
var transactionAmount = transaction.Amount;
var invoice = new Invoice();
// This line works fine:
var invoiceSubtotal = invoice.SubTotal;
// This line won't compile.
// Error: TransactionBase.Amount is inaccessible due to its protection level.
var invoiceAmount = invoice.Amount;
所以我最初的问题的答案是,“不”你不能隐藏公共(public)继承成员。上面的解决方案通过直接访问派生类型中的 protected 成员来伪造它,但它仍然有点糟糕。打字太多。
当然,既然我摆弄了所有这些,我发现一个更好的解决方案完全抛弃了 protected 成员并节省了我一些打字时间。顺便说一下,是的,我很尴尬,我没有立即跳到这个解决方案。
编辑:实际上,我回答中的第一个方法可能更好。对于第二个,当从交易转换为发票时,我会丢失“金额”或“小计”。
public abstract class TransactionBase
{
// There are some shared properties here.
}
public class Transaction : TransactionBase
{
public double Amount { get; set; }
}
public class Invoice : TransactionBase
{
public double SubTotal { get; set; }
}
关于C# "Rename"派生类中的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12325637/