Форум программистов, компьютерный форум, киберфорум
Наши страницы
C# для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.61/18: Рейтинг темы: голосов - 18, средняя оценка - 4.61
alexandrv2
0 / 0 / 0
Регистрация: 31.03.2018
Сообщений: 27
1

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

31.03.2018, 08:18. Просмотров 3484. Ответов 7
Метки нет (Все метки)

Добрый день! Помогите пожалуйста вызвать поле базового класса из метода производного класса. Код, составленный мною выводит результат неправильно, несмотря на обращение к полю базового класса base.Name:
Я — предок!
Я — Петров Николай Иванович

Я — отец!
Я — Петров Сергей Николаевич
Я — сын Петров Сергей Николаевича

а должен выводить

Я — предок!
Я — Петров Николай Иванович

Я — отец!
Я — Петров Сергей Николаевич
Я — сын Петров Николай Ивановича
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
namespace Predoc
{ class tPredoc
    {
        public string Name;
        public tPredoc(string Name) { this.Name = Name; }
        public virtual void Declaration() { Console.WriteLine("Я - предок!"); }
        public virtual void MyName() { Console.WriteLine($"Я - {Name}"); }
 
    }
    class tSon : tPredoc
    {
        public tSon(string Name):base(Name) {  }
        public override void Declaration() { Console.WriteLine("Я - отец!"); }
        public override void MyName()
        {
            base.MyName();
            Console.WriteLine($"Я - сын {base.Name}а");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            tPredoc ded=new tPredoc("Петров Николай Иванович");
            tSon otec = new tSon("Петров Сергей Николаевич");
           
            ded.Declaration();
            ded.MyName();
            Console.WriteLine();
 
            otec.Declaration();
            otec.MyName();
           
            Console.ReadKey();
 
 
        }
    }
}
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
31.03.2018, 08:18
Ответы с готовыми решениями:

Вызвать метод производного класса из базового класса
namespace patterns { public class BaseClass { public virtual void Action() ...

Ссылается ли на экземпляр производного класса переменная родительского типа в приведенном коде
Гербердт Шилдт не поленился, два раза повторил: "по ссылке на объект базового класса можно...

Доступ к методу родительского класса из метода свойства родительского класса
Не знаю правильно ли написал тему, ну суть такая, есть класс который описывает допустим шарик, а...

Статическое поле из производного класса
Есть три класса public class Птицы { public static Int32 ДлинаКрыльев; } public class Орлы...

Обращение к полю производного класса по ссылке базового класса
Описывается базовый и производный класс. В методе Main создается объект производного класса и...

7
IamRain
1767 / 1394 / 423
Регистрация: 02.08.2011
Сообщений: 4,085
31.03.2018, 08:40 2
У вас логическая ошибка в коде.

Наследование придумали для того, чтобы избавиться от дублирования кода.
Переопределив MyName в производном классе: Console.WriteLine($"Я - сын {base.Name}а");

Вы говорите: "Ты будешь сыном самого себя".

Нужно, чтобы сын хранил либо ссылку на отца, либо на его имя.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class tSon : tPredoc
    {
        public string FatherName {get; private set;}        
 
        public tSon(string Name, tPredoc father):base(Name) {
                FatherName = father.Name;
       }
       
      
 
        public override void Declaration() { Console.WriteLine("Я - отец!"); }
        public override void MyName()
        {
            base.MyName();
            Console.WriteLine($"Я - сын {FatherName}а");
        }
    }
 
// использование
tPredoc ded=new tPredoc("Петров Николай Иванович");
tSon otec = new tSon("Петров Сергей Николаевич", ded);
0
alexandrv2
0 / 0 / 0
Регистрация: 31.03.2018
Сообщений: 27
31.03.2018, 08:51  [ТС] 3
Спасибо за ответ.
А можно сделать тогда передачу имени предка при вызове метода из класса Program? Например, так:
C#
1
otec.MyName(ded);
Только получится, что в классе tPredoc метод MyName не имеет параметров, а в классе tSon будет иметь один. А это в языке не поддерживается(((
0
IamRain
1767 / 1394 / 423
Регистрация: 02.08.2011
Сообщений: 4,085
31.03.2018, 08:59 4
Можно добавить в сигнатуру метода MyName параметр, но не стоит этого делать, так как тут уже нарушается инкапсуляция.
В таком случае можно будет из клиентского кода кого угодно подсовывать в качестве отца, а такое в реальной жизни недопустимо. Имя отца должно быть хардкорно зашито в родословной.
0
31.03.2018, 08:59
alexandrv2
0 / 0 / 0
Регистрация: 31.03.2018
Сообщений: 27
31.03.2018, 09:12  [ТС] 5
Не совсем понял вот эту часть -

"Переопределив MyName в производном классе:
C#
1
Console.WriteLine($"Я - сын {base.Name}а");
Вы говорите: "Ты будешь сыном самого себя"."

Ведь в любом хелпере указано, что обратиться к конструктору, методу, полю или свойству родительского класса можно спокойно с помощью ключевого слова base. А на практике все совсем по другому?

http://turbopro.ru/index.php/yazyk-p...-klass-manager
При создании конструктора производного класса:

сначала вызывается конструктор базового класса, а затем вызывается конструктор текущего класса
Для вызова конструктора базового класса используется ключевое слово base
если базовый класс имеет несколько конструкторов, то необходимый указывается при определении конструктора производного класса;
если конструктор базового класса имеет параметры, то они включаются в список параметров производного класса.
Используя ключевое слово base можно вызвать метод или поле родительского класса, если оно имеет уровень доступа public
Или https://alekseygulynin.ru/nasledovanie-v-c/

Всю ночь сидел с примерами, но так и не понял, в чем ошибка.
0
IamRain
1767 / 1394 / 423
Регистрация: 02.08.2011
Сообщений: 4,085
31.03.2018, 09:40 6
Цитата Сообщение от alexandrv2 Посмотреть сообщение
А на практике все совсем по другому?
Нет, не по-другому.
Для начала определитесь, какую сущность вы моделируете.
1. Сущность - человек. У человека есть имя. Значит и у предка, и у наследника должно быть свойство Name.
Вы его добавили в базовый класс.
2. Далее нужно, чтобы предок и наследник по-разному выводили информацию о своей родословном. Для этого вы определили виртуальный метод MyName.
3. При выводе имени предку нужно знать только свое имя, а сыну - также имя отца, соответственно нужно где-то хранить эту дополнительную информацию.

В базовый класс выносятся только общие для всех членов иерархии свойства и поведение.

Тогда, по идее, в tPredoc тоже можно вынести имя отца, просто в таком случае вам не нужна будет иерархия классов, это будет что-то типа односвязного списка.

В рамках текущей задачи вполне корректно вынести в базовый класс Name, а у наследника добавить ссылку на имя отца.
0
alexandrv2
0 / 0 / 0
Регистрация: 31.03.2018
Сообщений: 27
31.03.2018, 13:20  [ТС] 7
Я ведь думаю как: Есть родитель - создан экземпляр этого класса, имеющий поля и методы (эта чать информации хранится в "куче" в оперативной памяти, в том числе и значение поля Name, раз уж это объект). Есть наследник - другой экземпляр второго класса, который наследует от родителя поле Name и метод MyName, чтоб его не описывать повторно. Но заполняется поле Name наследника уже из конструктора по ссылке в базовый класс :base(Name) - и это работает! Также работает и ссылка на метод в базовом классе base.MyName(); Не работает только ссылка на поле родителя base.Name.
0
IamRain
1767 / 1394 / 423
Регистрация: 02.08.2011
Сообщений: 4,085
31.03.2018, 13:34 8
Цитата Сообщение от alexandrv2 Посмотреть сообщение
Но заполняется поле Name наследника уже из конструктора по ссылке в базовый класс :base(Name)
Все верно. Вся прелесть наследования заключается в том, что вы конструируете объект, по сути, состояние(свойства, события, поля) и поведение(методы) которого формируется целой цепочкой типов.

Но все члены экземпляра остаются принадлежать одному единственному экземпляру.

Поэтому
Цитата Сообщение от alexandrv2 Посмотреть сообщение
Не работает только ссылка на поле родителя base.Name.
по вашему не работает. base.Name означает, что данное свойство берется не из текущего типа, а из типа родителя. Но относится то оно к текущему экземпляру.

По задумке проектировщиков языка все работает прекрасно.
0
31.03.2018, 13:34
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
31.03.2018, 13:34

Ссылка базового класса на объект производного класса
Граждане, объясните почему такое происходит. До того как проверил, думал, что если для ссылки...

Экземпляр класса как входные данные метода другого класса
Можно ли в качестве входных данных метода передать экземпляр метода другого класса? Если да, то как?

Обращение к методу дочернего класса из экземпляра родительского класса
Как обратиться к методу дочернего класса из экземпляра родительского класса? К примеру здесь как...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.