1 / 1 / 2
Регистрация: 03.11.2013
Сообщений: 50
1

Про вызов виртуального метода из конструктора

20.02.2016, 12:35. Показов 935. Ответов 6
Метки нет (Все метки)

Знаю, что нельзя вызывать виртуальный метод из конструктора, но не знаю как сделать иначе.
Есть класс Сотрудник с почасовой оплатой, в конструкторе получаю почасовую ставку для рассчета зарплаты. Но метод рассчета, который получает в качестве параметра эту почасовая ставку - виртуальный, так как для разных категорий сотрудников своя методика рассчета.
Логично было бы сразу при создании экземпляра рассчитать зарплату и сохранить её в свойстве Payment. То есть как раз вызвать виртуальный метод в конструкторе, и все работает неправильно.

Можно, конечно, вызывать метод в геттере свойства Payment, но тогда каждый раз при обращении зарплата будет рассчитываться заново. Тоже как-то неочень.

Как ещё можно решить эту задачу?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
20.02.2016, 12:35
Ответы с готовыми решениями:

Вызов виртуального метода в конструкторе
Помню расматривался этот вопрос на форуме - хочу освежить память почему при вызове виртуального...

Вызов виртуального метода при создании
Добрый вечер, библиотека навязала следующее поведение: - объект создан и валиден, если...

Вызов виртуального метода класса наследника из вектора
#include <iostream> #include <vector> using namespace std; class A { public: ...

Вызов виртуального метода базового класса из указателя производного
Допустим есть такой код: #include <iostream> class Base { public: virtual void f() {...

6
306 / 101 / 18
Регистрация: 04.07.2014
Сообщений: 571
20.02.2016, 13:28 2
Цитата Сообщение от Elfin83 Посмотреть сообщение
Логично было бы сразу при создании экземпляра рассчитать зарплату
Нет, не логично. Каждый метод должен заниматься своим делом. У конструктора дело -- создание верного объекта.
Расчёт зарплаты должен производиться в методе расчёта зарплаты.
0
1 / 1 / 2
Регистрация: 03.11.2013
Сообщений: 50
20.02.2016, 15:01  [ТС] 3
mporro, спасибо за ответ, но вы наверное меня не правильно поняли. Расчет зарплаты реализован в отдельном методе. Вопрос в том, откуда его вызвать, чтобы инициализировать поле payment.
Вот упрощенный базовый класс:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 abstract public class Employee
    {
         private static decimal payment = 0;
         public decimal Payment 
        {
            get { return payment; }
        }        
            
        public Employee (string name ="") 
        {
            //Вот здесь вызывается метод, происходит это раньше, 
            //чем в конструкторе потомка будет передан параметр, необходимый для рассчета
            //payment = CalculatePayment();
        }
abstract public decimal CalculatePayment();
Вот упрощенный класс сотрудника с почасовой оплатой:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class HourlyPaymentEmployee : Employee
    {
        public decimal Rate { get; private set; }       
        public HourlyPaymentEmployee(string name, decimal rate = 0m)
            : base(name)
        {                      
            Rate = rate;
        } 
        public override decimal CalculatePayment()
        {
            //Рассчет зарплаты по определенному алгоритму
            return payment;
        }
    }
0
306 / 101 / 18
Регистрация: 04.07.2014
Сообщений: 571
20.02.2016, 15:21 4
Elfin83
Если у Вас экземпляр HourlyPaymentEmployee рассчитывает зарплату в отдельном методе, то зачем Вы её сохраняете во внутреннее поле?

Добавлено через 12 минут
Как-то так должно выглядеть
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
abstract public class Employee {
    public abstract decimal calculatePayment();        
   
    public Employee (string name_) 
    {
           name = name_;
    }
    
    private string name;
}
 
class HourlyPaymentEmployee : Employee {
    public override decimal calculatePayment()
    {
         //здесь код расчёта зарплаты в зависимости от rate
         return payment;
    }
 
    public HourlyPaymentEmployee(string name_, decimal rate_): base(name_)
    {
        rate = rate_;
    }
 
    private decimal rate;
}
0
1 / 1 / 2
Регистрация: 03.11.2013
Сообщений: 50
20.02.2016, 15:28  [ТС] 5
mporro, мне нужна возможность извне получать зарплату каждого сотрудника, для этого в классе свойство Payment, как не используя поля передать это значение геттеру?
0
306 / 101 / 18
Регистрация: 04.07.2014
Сообщений: 571
20.02.2016, 16:03 6
Цитата Сообщение от Elfin83 Посмотреть сообщение
мне нужна возможность извне получать зарплату каждого сотрудника
Так вот её и можно получить, вызвав метод calculatePayment(), который является частью контракта Employee. A свойство payment совсем выкинуть, обращаться через только через метод.

P.S.
Если уже настолько нарушена архитектура, что сделать честно нельзя, то вызывайте из акцессора get метод calculatePayment. Сам calculatePayment тогда нужно сделать закрытым, чтобы не испортить интерфейс. В C# же можно как в Java переопределить private метод, да?
1
1 / 1 / 2
Регистрация: 03.11.2013
Сообщений: 50
20.02.2016, 18:42  [ТС] 7
mporro, всё, дошло, спасибо!
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
20.02.2016, 18:42
Помогаю со студенческими работами здесь

Вызов конструктора из конструктора и проверка правильности передаваемых параметров
Существует такой код: public Matrix(Double array) : this(array.GetLength(0),...

Полиморфизм: вызов метода базового класса, переопределенного метода и нового метода
В базовом классе метод помечен как virtual. Насколько я понял из книги: override означает, что...

Вызов конструктора из конструктора - ошибка
Айм водеринг. Но разве из одного конструктора нельзя вызвать другой (из StadoOvechek() вызвать...

Переопределение виртуального метода
Нужно написать виртуальный метод в родительском классе , который находит площадь круга. Затем...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru