Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

implement an interface but with different members names

I have IPrice interface:

public interface IPrice
{
    decimal TaxPercent { get; set; }
    decimal TotalDebt { get; set; }
    decimal Discount { get; set; }
    DiscountTypeEnum DiscountType { get; set; }
    decimal Commission { get; set; }
    DiscountTypeEnum CommissionType { get; set; }
}

I have interface IExtendPrice and its default implementation:

public interface IExtendPrice
{
    decimal TotalDebtWithoutTax { get; }
    decimal TaxSum { get; }
    decimal DiscountSum { get; }
    decimal CommissionSum { get; }
    decimal DebitPrice { get; }
}

public class ExtendPrice : IExtendPrice
    {
        private IPrice m_Price = null;
        public ExtendPrice(IPrice price)
        {
            m_Price = price;
        }

        public decimal TotalDebtWithoutTax { get { return (m_Price.TotalDebt / (1 + (m_Price.TaxPercent / 100))); } }
        public decimal TaxSum { get { return m_Price.TotalDebt - TotalDebtWithoutTax; } }
        public decimal DiscountSum
        {
            get
            {
                decimal discount = m_Price.Discount;
                if (m_Price.DiscountType == DiscountTypeEnum.PERCENTS)
                {
                    discount = discount * NetoPrice / 100;
                }
                return discount;
            }
        }

        public decimal CommissionSum
        {
            get
            {
                decimal commission = m_Price.Commission;
                if (m_Price.CommissionType == DiscountTypeEnum.PERCENTS)
                {
                    commission = commission * NetoPrice / 100;
                }
                return commission;
            }
        }

        public decimal NetoPrice { get { return CalculateNetoPrice(); } }



        private decimal CalculateNetoPrice()
        {
            decimal debitPrice = 0;
            if (m_Price.DiscountType == DiscountTypeEnum.COINS &&
                m_Price.CommissionType == DiscountTypeEnum.COINS)
            {
                //TotalDebtWithoutTax=X-Discount+Commission
                debitPrice = TotalDebtWithoutTax + m_Price.Discount - m_Price.Commission;
            }
            else if (m_Price.DiscountType == DiscountTypeEnum.COINS &&
               m_Price.CommissionType == DiscountTypeEnum.PERCENTS)
            {
                //TotalDebtWithoutTax=X-Discount+Commission*X/100
                debitPrice = (TotalDebtWithoutTax + m_Price.Discount) / (1 + m_Price.Commission / 100);
            }
            else if (m_Price.DiscountType == DiscountTypeEnum.PERCENTS &&
               m_Price.CommissionType == DiscountTypeEnum.COINS)
            {
                //TotalDebtWithoutTax=X-Discount*X/100+Commission
                debitPrice = (TotalDebtWithoutTax - m_Price.Commission) / (1 - m_Price.Discount / 100);
            }
            else if (m_Price.DiscountType == DiscountTypeEnum.PERCENTS &&
               m_Price.CommissionType == DiscountTypeEnum.PERCENTS)
            {
                //TotalDebtWithoutTax=X-Discount*X/100+Commission*X/100
                debitPrice = TotalDebtWithoutTax / (1 - m_Price.Discount / 100 + m_Price.Commission / 100);
            }
            return debitPrice;
        }
    }

I have classes such as Invoice, PurchaseInvoice, DeliveryNote that each: 1. implements IPrice using its members. 2. implements IExtendPrice using ExtendPrice default implementation. Such class can look like:

public class Invoice : IPrice, IExtendPrice
    {
        public virtual decimal TotalDebt { get; set; }
        public virtual decimal TaxPercent { get; set; }
        public virtual decimal Discount { get; set; }
        public virtual DiscountTypeEnum DiscountType { get; set; }
        public virtual decimal Commission { get; set; }
        public virtual DiscountTypeEnum CommissionType { get; set; }

        private IExtendPrice extendPrice = null;
        public Invoice()
        {
            extendPrice = new ExtendPrice(this);
        }

        public decimal TotalDebtWithoutTax { get { return extendPrice.TotalDebtWithoutTax; } }
        public decimal TaxSum { get { return extendPrice.TaxSum; } }
        public decimal DiscountSum { get { return extendPrice.DiscountSum; } }
        public decimal CommissionSum { get { return extendPrice.CommissionSum; } }
        public decimal DebitPrice { get { return extendPrice.DebitPrice; } }
    }

But noe I have class that called CreditInvoice. It has the following member:

    public decimal TotalCreditSumWithoutTax
    {
        get { return Math.Round(m_TotalCreditSum / (1 + (m_Tax / 100)), 2); }
    }

Which is the same implementation like ExtendPrice's TotalDebtWithoutTax. The difference is with it's name instead of credit - debit/debt.

What is the best practice to enables the use of ExtendPrice in CreditInvoice without changing the names of its members?

like image 1000
Naor Avatar asked Jul 27 '11 15:07

Naor


2 Answers

Use an explicit interface implementation for that member:

class CreditInvoice : IExtendPrice
{
    // ...
    public decimal TotalCreditSumWithoutTax { /* ... */ }


    // Only seen when accessing an instance by its IExtendPrice interface
    decimal IExtendPrice.TotalDebtWithoutTax {
        get { return TotalCreditSumWithoutTax; }
    }
}
like image 152
Cameron Avatar answered Nov 15 '22 22:11

Cameron


You have to do something like this:

public decimal TotalDebtWithoutTax { get { return TotalCreditSumWithoutTax; } }

Although when you read that, it does sound as though there are some design flaws in your code.


In the comments you make it clear that you want to implement the interface, but not implement a method named TotalDebtWithoutTax. That's not possible. In order to implement an interface, you need to implement all the methods.

My guess is that your choice of name for TotalDebtWithoutTax is too constraining. You are probably objecting to having to implement it with a method name TotalCreditSumWithoutTax. How can a credit be a debit? I guess you'll need to generalise the underlying interface to remove this impedance.

like image 34
David Heffernan Avatar answered Nov 15 '22 22:11

David Heffernan