Использование метода из производного класса с объектом типа базового класса - PullRequest
1 голос
/ 21 ноября 2011

В моем производном классе есть метод, которого нет в базовом классе. Можно ли использовать метод производного класса для объекта с типом базового класса? Я знаю, что могу переместить метод в свой базовый класс, но я не думаю, что должен это делать ..

Вот код:

Я хочу использовать CalculateInterest () для моих учетных записей в цикле, но все учетные записи имеют тип Account, а не SavingsAccount.

Метод в классе SavingsAccount:

 public decimal CalculateInterest()
        {
            return AcctBalance * interestRate;
        }

Loop in Main:

List<Account> accounts = new List<Account>();

            Account sAcct1 = new SavingsAccount(200, 0.10M);
            Account sAcct2 = new SavingsAccount(300, 0.12M);
            Account cAcct1 = new CheckingAccount(500, 2.00M);
            Account cAcct2 = new CheckingAccount(400, 1.50M);

            accounts.Add(sAcct1);
            accounts.Add(sAcct2);
            accounts.Add(cAcct1);
            accounts.Add(cAcct2);
foreach (Account account in accounts)
            {
                account.Debit(decimal.Parse(Console.ReadLine()));
                account.Credit(decimal.Parse(Console.ReadLine()));
                if (account.GetType().ToString().Contains("SavingsAccount"))
                {
                    //calculate interest if object is a savings account
                }
            }

Ответы [ 4 ]

0 голосов
/ 21 ноября 2011

Я собираюсь сделать ответ, вдохновленный частями других ответов:)

Я бы оставил Debit() и Credit() в качестве методов на Account вместо того, чтобы скрывать их внутри метода черного ящика Process(), поскольку в реальной жизни Accounts можно списывать и кредитовать, так что это кажется более подходящая модель для меня. Я бы предложил один из двух способов включить метод CalculateInterest().

Первый вариант : Как указано @Dave Newton, определите интерфейс IInterestBearingAccount, в котором есть метод CalculateInterest(), а затем реализуйте его в SavingsAccount. Ваш цикл в main может затем сказать:

var interestBearingAccount = account as IInterestBearingAccount;

if (interestBearingAccount != null)
{
    interestBearingAccount.CalculateInterest();
}

Это дает вам то, что вы хотите, без знания того, что SavingsAccounts начисляет проценты, в то время как другие Accounts не относятся к методу Main, где он не принадлежит.

Второй вариант - по касательной из ответа @Dave Newton - иметь пустой virtual метод на Account с именем CalculateSupplementals (или что-то в этом роде) и Main вызывать его , SavingsAccount может реализовать его для расчета процентов, а CheckingAccount ничего не может сделать. Метод базового класса имеет общее имя, так что реализующие классы могут использовать его как ловушку для выполнения дополнительных вычислений, если это необходимо для типа учетной записи, которую они представляют; он не помещает информацию о деталях производного класса в базовый класс и предоставляет где-то для других классов работу, специфичную для них.

Мои личные предпочтения, вероятно, являются первым вариантом, поскольку они ничего не добавляют в иерархию только для удовлетворения потребностей производного класса.

0 голосов
/ 21 ноября 2011

Это, кажется, специфическая вещь для языка, больше, чем объектная ориентация. В частности, Java, хотя код не совсем Java.

В любом случае, если вы хотите иметь структуру одного типа и вызывать метод подкласса, просто выполните приведение объекта, предварительно используя оператор instanceof для проверки класса.

Вероятно, это не самое элегантное решение, оно зависит от вашей проблемы, поэтому трудно сказать, какой шаблон или способ организации вашего кода вы можете использовать с имеющейся информацией.

Одна подсказка, которую предоставляет ваш код, заключается в том, что вы обрабатываете все учетные записи, а для некоторых из них начисляются проценты. Похоже, что ваш метод может выполнять две и более операции одновременно, и, возможно, потребуется разделить его на два или более метода для улучшения читабельности (возможно). Что бы вы ни пытались сделать, подумав о правильном дизайне, вы можете решить проблему за вас.

0 голосов
/ 21 ноября 2011

Ну, вы можете попытаться привести каждую учетную запись к Сберегательному счету

if (account as SavingsAccount != null) { //calculate interest }

Но я бы сказал, что нет ничего плохого в том, что реализована CalcuInInrest в базовом классе, а затем переопределил бы его при необходимости (например, SavingsAccount переопределил бы его, CheckingAccount - нет), как упомянуто Дейвом Ньютоном.

Может быть, лучший способ - это инкапсулировать обработку учетной записи в новый метод (может быть, под названием «процесс») и применять его соответствующим образом в каждом случае. Например. в аккаунте

public void process()
{
                this.Debit(decimal.Parse(Console.ReadLine()));
                this.Credit(decimal.Parse(Console.ReadLine()));
}

и затем переопределить это в SavingsAccount

public override void process()
{
                base.process();
                //now calculate interest
}

Это позволило бы избежать реализации метода в базовых классах, который ничего не делает.

0 голосов
/ 21 ноября 2011

В этом случае, вероятно, лучше всего иметь реализацию по умолчанию calculateInterest() в базовом классе, которая ничего не делает.

Подклассы будут переопределены для обеспечения расчета процентов по типу счета.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...