簡體   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