繁体   English   中英

C#“重命名”派生类中的属性

[英]C# “Rename” Property in Derived Class

当你读到这篇文章时,你会非常想提出一些建议,比如“由于以下原因,这是一个坏主意......”

忍受我。 我知道还有其他方法可以解决这个问题。 这个问题应该被认为是琐事。

假设您有一个“交易”类,它具有所有交易的共同属性,例如发票,采购订单和销售收据。

让我们以交易“金额”的简单示例为例,这是给定交易的最重要的货币金额。

public class Transaction
{
    public double Amount { get; set; }

    public TxnTypeEnum TransactionType { get; set; }
}

此数量可能在派生类型中具有更具体的名称...至少在现实世界中。 例如,以下值实际上都是相同的:

  • 交易 - 金额
  • 发票 - 小计
  • PurchaseOrder - 总计
  • 销售收据 - 金额

所以现在我想要一个派生类“Invoice”,它有一个小计而不是一般命名的Amount。 理想情况下,以下两种情况都是正确的:

  1. 在Transaction的实例中,Amount属性将是可见的。
  2. 在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; }
}

但当然,在任何Invoice实例上仍然可以看到Transaction.Amount。

谢谢参观!

谢谢你的帮助。

好吧,当派生类是基础实例时,当然不能“隐藏”基类上的公共属性。 在我脑海深处的某个地方,我已经知道了。 卫生署!

通过使用名为TransactionBase的第三个类,我最终得到了语法糖,以表达我对消费者的需求。 这个类是抽象的,包含所有交易的共享,非别名的东西,如货币,汇率,创建/修改日期和时间,交易日期等......除了Amount这样的别名之外。

在这里,我只显示有问题的Amount属性:

public abstract class TransactionBase
{
    protected virtual double Amount { get; set; }
}

然后Transaction看起来像这样:

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;

所以我原来的问题的答案是,“不”你不能隐藏公共继承成员。 上面的解决方案通过直接在派生类型中访问受保护的成员来伪造它,但它仍然很糟糕。 打字太多了。

当然,现在我摆弄和摆弄所有这些,我看到一个更好的解决方案完全抛弃了受保护的成员并节省了一些打字。 顺便说一句,是的,我很尴尬,我没有立即跳到这个解决方案。

编辑:实际上,我的答案中的第一个appraoch可能会更好。 对于第二个,当从交易转换为发票时,我将失去“金额”或“小计”。

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; }
}

简而言之,你不能这样做。

总之,您可以通过编码接口来模拟这一点!

public class Transaction
{
    public double Amount { get; set; }
}
public interface IInvoice
{
    public double? SubTotal { get; set; }
}
public class Invoice : Transaction, IInvoice
{
    public double? SubTotal
    {
        get
        {
            return Amount;
        }
        set
        {
            Amount = value ?? 0.0f;
        }
    }
}

你正在寻找的确切行为在语法上没有意义。 如果Invoice继承Transaction ,那么它是一种事务,编译器要求它继承其所有属性。

我认为,您正在寻找的一般行为是封装,可以通过接口来实现。

public interface IInvoice
{
    double? Amount { get; set; }
}

public interface ITransaction
{
    double? SubTotal { get; set; }
}

要求代码的使用者使用这些接口,然后隐藏实现细节。


所以现在,这些类可以按照你想要的方式运行。 SubTotal仍将对 (Invoice)可见,但将隐藏到界面 (IInvoice)。

public class Transaction : ITransaction
{
    public double? SubTotal { get; set; }
}

public class Invoice : IInvoice
{
    public double? Amount
    {
        get { return base.SubTotal; }
        set { base.SubTotal = value; }
    }
}

在这个例子中,我建议使用组合而不是继承。 主要原因是Transaction的基本实现似乎永远不会以通过继承的方式使用。 您可以将事务隐藏为Invoice的受保护或私有成员,并使用Invoice的公共属性公开/操作它。

一个这样的例子看起来像:

public class Invoice
{
        private readonly Transaction _transaction; 
        public Invoice():this(new Transaction())
        {
        }
        public Invoice(Transaction transaction)
        {
            _transaction = transaction;
        }

        // This property should hide the generic property "Amount" on Transaction
        public double? SubTotal
        {
            get
            {
                return _transaction.Amount;
            }
            set
            {
                _transaction.Amount = value ?? 0.0f;
            }
        }

        public double RemainingBalance { get; set; }
    }

如何使用隐式转换运算符?

class Program
{
    static void Main(string[] args)
    {
        var transaction = new Transaction();
        var transactionAmount = transaction.Amount;

        var invoice = new Invoice();
        var invoiceSubTotal = invoice.SubTotal;

        Transaction fromInvoiceToTrans = invoice;
        var fromInvoiceToTransAmount = fromInvoiceToTrans.Amount;

    }
}

public class Transaction
{
    public decimal Amount {get; set;}
}

public class Invoice
{
    public decimal SubTotal
    {
        get;
        set;
    }

    public static implicit operator Transaction(Invoice invoice)
    {
        return new Transaction
        {
            Amount = invoice.SubTotal
        };
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM