Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.85/40: Рейтинг темы: голосов - 40, средняя оценка - 4.85
9 / 9 / 2
Регистрация: 25.11.2012
Сообщений: 115

Можно ли не передавать значения из конструктора дочернего класса в базовый

19.04.2014, 11:14. Показов 8069. Ответов 35
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
У меня есть абстрактный класс (пусть будет A), от которого наследуются 4 класса (соответственно, B,C,D,E).
В конструкторах дочерних классов не требуется указания никаких других переменных кроме тех, что есть в конструкторе базового класса (пусть это будут int x и int y).
Во время создания объекта класса и далее, во время присваивания и изменения значений переменных, необходимо проверять допустимость значений. Для каждого из дочерних классов параметры свои.
Таким образом, если описать кратко, выходит что-то наподобие такого (проверки значений упрощу до минимума ибо суть вопроса не в них):
Базовый класс A:
Кликните здесь для просмотра всего текста
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
public abstract class A
{
private int x;
private int y;
 
public int X
{
get {return x;}
set
{
if(IsRight(value)) x=value;
else throw new Exception("Параметр указан неверно!");
}
}
 
public int Y
{
get {return y;}
set
{
if(IsRight(value)) y=value;
else throw new Exception("Параметр указан неверно!");
}
}
 
public A(int x, int y)
{ //присваиваем через свойства, чтобы не писать дважды одни и те же проверки
this.X = x;
this.Y = y;
}
 
public abstract bool IsRight(int num);
}


Класс, к примеру, B (одного класса хватит для описания вопроса, остальные классы работают по аналогии с этим)
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
public abstract class B : A
{
public B(int x, int y) : base(x,y)
{
}
 
public override bool IsRight(int num)
{
return num > 200 && num < 1000;
}
}


Теперь к сути вопроса.
В вышеописанном коде, по идее, при инициализации элемента через конструктор происходит следующее:
Кликните здесь для просмотра всего текста

1. Переменные из конструктора дочернего класса передаются в конструктор базового класса.
2. В конструкторе переменные передаются в свойства.
3. В свойствах значение переменной передается в абстрактный метод проверки.
4. Абстрактный метод означает, что, по сути, выполнится соответствующий метод дочернего класса, в него значения и передаются.
5. Метод дочернего класса возвращает результат в свойства базового класса.
6. В зависимости от результата происходит присваивание или генерация исключения.


Но можно описать код по другому:
1. Не передавать значения из конструктора дочернего класса в базовый.
2. Выполнять проверку значений вызовом метода (из дочернего конструктора вызов метода этого же класса).
3. Сделать переменные базового класса не private, а protected; и присваивать им значения после проверки.

Вопрос: Какое написание кода будет более правильным?
З.Ы. Может, есть еще варианты, не рассмотренные мной, если предложите что-то другое - милости просим =)
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
19.04.2014, 11:14
Ответы с готовыми решениями:

Копирование дочернего класса в базовый
Доброго времени суток. Меня интересует вопрос. Имеется вот такой код: #include &lt;iostream&gt; using namespace std; class A...

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

ООП. Обращение к свойству дочернего класса через базовый абстрактный
Всем привет, появился у меня такой вопрос Есть у меня абстрактный класс Animal у которого есть 2 поля - имя и год рождения. Дальше есть...

35
 Аватар для Spawn
995 / 893 / 354
Регистрация: 24.03.2014
Сообщений: 2,381
Записей в блоге: 2
19.04.2014, 17:14
Студворк — интернет-сервис помощи студентам
fadeinmad, Microsoft'овская реализация обработчиков событий Вас тогда должна просто в кому ввести, если Вы так относитесь к примеру с private методом, который кроме самого разработчика не вызовет никто.
С точки зрения грамотного публичного метода там будет проверка на правильное значение и ArgumentException в случае чего. Специально же для себя создавать Enum с возможными значениями мало кто будет, по крайней мере не сразу. Сам Гради утверждает замечательную вещь - ни одна сложная система сразу не заработает, любая сложная система эволюционирует из простой и работающей.

Цитата Сообщение от fadeinmad Посмотреть сообщение
во всех ситуациях, когда можно не использовать switch, его лучше не использовать
А Рихтер свойства не любит, тоже не использовать скажете?
0
713 / 680 / 126
Регистрация: 30.03.2012
Сообщений: 1,124
19.04.2014, 17:23
Возможно, что для Вашей конкретной задачи это и подходит, но ради интереса посмотрите Рефлектором или чем еще, как реализованы абстрактные классы в NET. Пустые методы, пустые поля и пустые автосвойства. Ничего больше. Они определяют только общее, что есть у всех, реализация везде своя.
Вот Вам как пример.
уж не считаете ли вы что, например, ExecuteReader не являющийся абстрактным на вашем скриншоте - пустой?
или просто коряво выразили мысль?)
0
9 / 9 / 2
Регистрация: 25.11.2012
Сообщений: 115
19.04.2014, 17:29  [ТС]
Цитата Сообщение от insite2012 Посмотреть сообщение
Именно так реализованы классы в NET, а их мнение что-то да значит...
Не буду спорить, но останусь при своем мнении.
К тому же, мы все-таки слишком далеко ушли от темы.

Добавлено через 5 минут
Цитата Сообщение от Spawn Посмотреть сообщение
С точки зрения грамотного публичного метода там будет проверка на правильное значение и ArgumentException в случае чего. Специально же для себя создавать Enum с возможными значениями мало кто будет, по крайней мере не сразу.
Даже для себя стоит писать так, как писал бы для другого, ибо уже через пару дней, вы можете и не разобраться в том, что натворили.

Цитата Сообщение от Spawn Посмотреть сообщение
Сам Гради утверждает замечательную вещь - ни одна сложная система сразу не заработает, любая сложная система эволюционирует из простой и работающей.
Согласен, но все же стоит писать так, чтобы минимизировать будущие возможные изменения, возникающие при росте и развитии системы. Иначе код начнет изменяться, путаться, в нем лавинообразно будет расти количество допускаемых неточностей и ошибок, и система "эволюционирует из простой и работающей" в сложную еле-еле работающую или не работающую вовсе.

Цитата Сообщение от Spawn Посмотреть сообщение
А Рихтер свойства не любит, тоже не использовать скажете?
Свойства, в принципе, довольно грамотное решение. Я их сторонник. Но мне стало интересно, какие аргументы приводит Рихтер против использования свойств. Я, к своему сожалению, их не знаю.
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
19.04.2014, 17:32
Цитата Сообщение от Tessen Посмотреть сообщение
уж не считаете ли вы что, например, ExecuteReader не являющийся абстрактным на вашем скриншоте - пустой?
или просто коряво выразили мысль?)
Он и не пустой. Я ранее говорил, что абстрактный класс может содержать и обычные методы, с реализацией...
0
9 / 9 / 2
Регистрация: 25.11.2012
Сообщений: 115
19.04.2014, 17:32  [ТС]
К тому же, свойства - прямое следствие применения инкапсуляции как одного из принципов ООП. А вот пренебрежение принципа наследования и использование вместо него switch уже нарушение ООП. Я же не говорю, что свитч не надо использовать, я говорю, что его не стоит использовать там, где более уместно наследование.
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
19.04.2014, 17:34
Цитата Сообщение от fadeinmad Посмотреть сообщение
А вот пренебрежение принципа наследования и использование вместо него switch уже нарушение ООП
Ну и вот скажите, каким боком связано использование switch и нарушение ООП? Что-то мне это ну никак непонятно...
0
713 / 680 / 126
Регистрация: 30.03.2012
Сообщений: 1,124
19.04.2014, 17:39
Свойства, в принципе, довольно грамотное решение. Я их сторонник. Но мне стало интересно, какие аргументы приводит Рихтер против использования свойств. Я, к своему сожалению, их не знаю.
свойство, это метод, который выглядит как поле
собственно из того что это вызов метода, следует что он несколько менее шустр, чем прямое чтение поля

Добавлено через 3 минуты
Именно так реализованы классы в NET, а их мнение что-то да значит..
я таки не соглашусь
то, что кто то реализовал в .net класс еще не значит что эта реализация является самой лучшей и подходящей к каждому конкретному случаю

к примеру посмотрите на реализацию классов кодировки в .net, мешанина unsafe-кода, вероятно потому, что .net используется в самых разных по нагрузке проектах и просадка производительности в нем неприемлима
однако, если вам понадобится дописать свою кодировку (например, потому что майкрософт решили, что в сильверлайте некоторые кодировки не нужны), вряд ли вы будете писать тонны unsafe-кода, особенно если пара милисекунд производительности вам не критична
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
19.04.2014, 17:40
Цитата Сообщение от Tessen Посмотреть сообщение
свойство, это метод, который выглядит как поле
Ну да, если в Ildasm посмотреть то свойство и будет развернуто на два метода... И неявное поле...
0
9 / 9 / 2
Регистрация: 25.11.2012
Сообщений: 115
19.04.2014, 17:43  [ТС]
Цитата Сообщение от insite2012 Посмотреть сообщение
Ну и вот скажите, каким боком связано использование switch и нарушение ООП? Что-то мне это ну никак непонятно...
Не использование switch - нарушение. А пренебрежение наследованием. =)
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
19.04.2014, 17:46
Цитата Сообщение от fadeinmad Посмотреть сообщение
Не использование switch - нарушение. А пренебрежение наследованием. =)
Ну хорошо. Вопрос: у вас метод, который в зависимости от параметра должен вернуть одного из наследников (возвращаемое значение-базовый класс). Что вы используете для выбора? Кучу if-else?
В этом как раз и прелесть наследования: в зависимости от условия (к примеру, прописанного в файле конфигурации) приложение решает, что ему выбрать. И самое хорошее-при смене возвращаемого значения не надо менять код, а только изменить строку в файле конфигурации.
0
9 / 9 / 2
Регистрация: 25.11.2012
Сообщений: 115
19.04.2014, 22:51  [ТС]
Цитата Сообщение от insite2012 Посмотреть сообщение
Ну хорошо. Вопрос: у вас метод, который в зависимости от параметра должен вернуть одного из наследников (возвращаемое значение-базовый класс). Что вы используете для выбора? Кучу if-else?
По сути, куча if-else это все равно что switch, даже хуже.
Я бы сделал в базовом классе абстрактный метод "Вернуть тип". Потом, при создании наследников описывал бы метод, как возврат их типа с помощью базовой переменной.

C#
1
2
3
4
5
6
//код в наследнике
public MyParent GetChildElement()
{
MyParent elementToReturn = this.MyChildValue;
return elementToReturn;
}
где базовый класс MyParent, а наследник - MyChild.

Таким образом, при вызове метода GetChildElement() мы автоматически получаем элемент дочернего класса в родительской переменной. Взятие текущего элемента через this.MyChildValue или создание нового через new MyChild(/*параметры*/) - на выше усмотрение в зависимости от поставленной задачи.
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
19.04.2014, 23:03
Цитата Сообщение от fadeinmad Посмотреть сообщение
По сути, куча if-else это все равно что switch, даже хуже.
Я бы сделал в базовом классе абстрактный метод "Вернуть тип". Потом, при создании наследников описывал бы метод, как возврат их типа с помощью базовой переменной.
Если мне не изменяет память, кто-то хотел уменьшить количество однообразного кода...
Ну а по операторам - так можно и половину языка выкинуть (хотя мне, честно, не понятно, чем и что тот же switch нарушает). Нормальный оператор, как и все.
0
9 / 9 / 2
Регистрация: 25.11.2012
Сообщений: 115
19.04.2014, 23:08  [ТС]
Цитата Сообщение от insite2012 Посмотреть сообщение
Если мне не изменяет память, кто-то хотел уменьшить количество однообразного кода...
Уменьшить количество кода и увеличить надежность.
В принципе, тут получаются примерно те же 3-4 строки на каждый класс.
Но теперь, при создании наследника, вам достаточно переопределить в нем этот метод, а не лезть в базовый класс и менять в нем методы.
Базовый класс после его создания мы даже не трогаем.
Нет никаких числовых параметров, которые надо запоминать и куда-то передавать. Не надо ничего такого.
Код становится понятнее, надежнее и проще, как бы там ни казалось.
0
52 / 45 / 4
Регистрация: 07.10.2010
Сообщений: 95
19.04.2014, 23:35
Почему то все, начиная изучать ООП особо любят наследование. И считают что оно помогает от дублирования кода.
Нет. Оно делает зачастую сложно переносимый и сложно расширяемый код.
Ну к примеру - Нам нужна та же проверка, но уже другого класса. Как ее выдрать со старой реализации и прикрутить к новой.
Или например - при этих условиях проверяем та, при других так. Городить два класса? Вводить всякие свичи в проверку?
Я б наверное всю валидатционную логику исключил из сущности. Создал бы класс Validator, который реализует какой то интерфейс IValidator и принимает в конструкторе валидируюмую сущность. И еще один класс - MultyTargetValidation - а он уже содержал бы в себе коллекцию IValidator, и просто проходился по коллекции и запeскал какой нибудь Validate()
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
19.04.2014, 23:40
Нет, я так и не понял, к чему все это: один метод, второй... Наследник автоматически является и базовым , и к чему все эти методы??? Вот Вам, классическое наследование. Нигде ничего не переопределяется. Но при изменении достаточно заменить одну строчку, и тип соединения сразу меняется. Безо всяких переписываний методов. Разве это не удобно? Именно это и есть наследование (и его применение).
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.Common;
using System.Data.Odbc;
using System.Data.OleDb;
using System.Data.SqlClient;
using System.Configuration;
 
namespace ConsoleApplication2
{
    enum DataProvider
    { SqlServer, OleDb, Odbc, None }
    class Program
    {
        static void Main(string[] args)
        {
            
            DataProvider dp = DataProvider.None;
            IDbConnection myConn;
            string connStr = ConfigurationManager.AppSettings["provider"];
            if (Enum.IsDefined(typeof(DataProvider), connStr))
                dp = (DataProvider)(Enum.Parse(typeof(DataProvider), connStr));
 
            myConn = GetConnection(dp);
           
            //Тут используем наше соединение... первоначально проверив на null...
           
 
            Console.WriteLine("You connection is: {0}", myConn.GetType().Name);
            Console.ReadLine();
        }
        static DbConnection GetConnection(DataProvider dp)
        {
            DbConnection conn = null;
            switch (dp)
            {
                case DataProvider.Odbc:
                    conn = new OdbcConnection();
                    break;
                case DataProvider.OleDb:
                    conn = new OleDbConnection();
                    break;
                case DataProvider.SqlServer:
                    conn = new SqlConnection();
                    break;
            }
            return conn;
        }
    }
}
XML
1
2
3
4
5
6
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="provider" value="SqlServer"/>
  </appSettings>
</configuration>
Для изменения типа соединения мне достаточно заменить всего одно слово. А сколько методов пришлось бы переписывать Вам?
0
9 / 9 / 2
Регистрация: 25.11.2012
Сообщений: 115
20.04.2014, 00:08  [ТС]
Цитата Сообщение от insite2012 Посмотреть сообщение
А сколько методов пришлось бы переписывать Вам?
Если делать, как я предлагал, то либо одну строчку, как и вам, либо вообще ничего не менять. Это в зависимости от необходимых изменений.

Цитата Сообщение от serefa Посмотреть сообщение
Почему то все, начиная изучать ООП особо любят наследование. И считают что оно помогает от дублирования кода.
Нет. Оно делает зачастую сложно переносимый и сложно расширяемый код.
Ну к примеру - Нам нужна та же проверка, но уже другого класса. Как ее выдрать со старой реализации и прикрутить к новой.
Я бы не сказал, что я начинающий программист на С#, хотя иногда и возникают такие вопросы, которые присущи начинающим, но все равно являюсь сторонником соблюдения принципов ООП. Использование наследования предполагает, что эта функция присуща только необходимому нам набору объектов. Это не порождает переносимый и сложно расширяемый код, так как при расширении в этом случае просто создается еще один наследник, переопределяющий этот метод.

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

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

А если продолжать вашу идею, то можно тогда сразу для написания небольшой программы сразу создавать множество интерфейсов в стиле "а вдруг они понадобятся еще"... А потом и каждый класс компилировать в отдельной библиотеке, потому что "а вдруг он понадобится мне в другом проекте..."
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
20.04.2014, 00:08

ООП в C++: Вызов родительского конструктора с параметром при создании объекта дочернего класса
Здравствуйте! Столкнулся с такой проблемой: если есть родительский класс с конструктором, то при создании дочернего объекта от этого...

Почему в списке инициализации конструктора дочернего класса нельзя вызывать конструктор родительского через его пространство имён?
Есть класс D и от него порождён класс Wd Тут вот например всё работает корректно (использую обращение ч/з пространство имён класса...

Почему при вызове конструктора из конструктора нельзя передавать this как аргумент?
Есть такой код: public class Order { { } Order(){ this(this.hashCode());//ошибка тут } ...

Как передавать значения строкового типа в конструктор через объект класса?
Как передавать значения строкового типа в конструктор через объект класса? Или просто, как передавать знач строкового типа в конструктор? ...

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


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

Или воспользуйтесь поиском по форуму:
36
Ответ Создать тему
Новые блоги и статьи
Про "Windows must die!"
kumehtar 04.11.2026
Знаете, чет накатило. . . . Когда-то это было почти боевым кличем: мол, нормальный человек сидит на DOS, OS/ 2 или Linux, а вот это вот - Must Die. А теперь человек произносит «мастдай» с усмешкой - и. . .
Красочные поля с номером страницы svg+background-image
russiannick 04.11.2026
Красочные поля с номером страницы не менее важны чем в эпоху бумажных книг. Посему спешу представить почтеннейшей публике этот важный инструмент который эти поля и формирует. В процессе разработки. . .
Вступаем в новую фазу генерации favicons, векторную.
russiannick 02.11.2026
Теперь нет нужды скрывать что используется простой svg. Исходный код изображения помещаем в поле и жмем кнопку. Исходник преобразуется в вид корректный для помещения в favicon или в url(). Нажатие. . .
Генератор паролей (вариант №4)
Maks 01.11.2026
После публикации 3-го варианта генератора паролей, разослал его своим коллегам (с целью оценки), в итоге были получены следующие рекомендации: 1. Вернуть возможность использования знаков | 1 l I;. . .
Генератор паролей (вариант №3)
Maks 30.10.2026
Финальная версия генератора паролей 1С. Доработка решения в этот раз коснулась только визуальной части, а именно, добавлен реквизит ДопПараметры (тип Булево), который скрывает/ отображает реквизиты:. . .
Магическое мышление и магия, современная наука не отличима от магии (говорит ИИ Джемени)
zorxor 30.10.2026
Джемени, расскажи, пожалуйста, что такое магическое мышление, что такое магия, почему современная наука чем-то напоминает магию? Фраза «Любая достаточно развитая технология неотличима от магии». . .
За какое время ИИ может подобрать пароль по хешу (рассказывает Джемени ИИ)
zorxor 30.10.2026
Расскажи, Джемени, если известен хэш МД5, например, за сколько ИИ сможет подобрать соответствующий пароль? Искусственный интеллект (ИИ) может подобрать простой или средний по сложности пароль по. . .
Кто убил Suno? Почему наше солнышко погасло? (диалог с ИИ Джемени)
zorxor 30.10.2026
Как убивали Suno. Хронология. «Убийство» музыкальной нейросети Suno — это затяжной процесс, в котором технологический хайп стартапа разбился о жесткую реальность судебных исков от гигантов. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru