Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.50/8: Рейтинг темы: голосов - 8, средняя оценка - 4.50
4 / 3 / 1
Регистрация: 30.11.2021
Сообщений: 101

Объект наследованного класса, содержащий объекты родительского класса, соседей по листу

13.09.2023, 06:49. Показов 2603. Ответов 34

Студворк — интернет-сервис помощи студентам
Я запутался в проблеме организации бизнес-логики.
Есть верхний уровень описания структуры с таим вот листом:
C#
1
2
3
4
5
6
7
8
public class TTFont
    {
        //всякие штуки
 
        private List<Glyph> glyphs;
 
        //всякие методы-конструкторы
     }
И в этом листе лежат объекты, среди которых есть обычные глифы типа
C#
1
2
3
4
5
[Serializable]
    public class Glyph
    {
       //всякие переменные, требуха и методы
    }
А потом я столкнулся с фактом, что также в этом листе лежат комбинированные глифы, которые внешне имеют те же методы типа GetWidth(), Draw() и т.п., но состоят из нескольких уже имеющихся простых глифом и правил их комбинирования, ну я и написал:

C#
1
2
3
4
5
public class CombinedGlyph : Glyph
    {
        private List<Glyph> glyphs;
        private List<TransformationEntry> transformations;
    }
Но вот дальше я не уверен в этакой конструкции. Не уверен как организовать конструкторы, как обойти ситуацию когда один член листа ссылается на другого члена листа, и в этом листе могут быть всякие перестановки, а также лист может заполняться в разных порядках, и если случится так, что я добавляю в лист комбинированный глиф, а до глифа, входящего в его состав еще не добрался...

Подскажите, возможно есть устоявшийся прием организации для таких случаев?
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
13.09.2023, 06:49
Ответы с готовыми решениями:

Как обратиться к полю объекта дочернего класса если он(объект) находится в массиве типа родительского класса?
Как обратиться к полю объекта дочернего класса если он(объект) находится в массиве типа родительского класса? Можно ли это сделать без...

Использование метода из наследованного класса к объекту базового класса
Есть метод public void OpExp() { if (Person._age&lt;18) Console.WriteLine(&quot;Вы не можете...

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

34
2298 / 1614 / 400
Регистрация: 26.06.2017
Сообщений: 4,780
Записей в блоге: 1
13.09.2023, 12:06
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от LexMcLinn Посмотреть сообщение
Буква Й приведена как пример.
В моём ответе тоже, но это никак не меняет сам подход к реализации.
0
4 / 3 / 1
Регистрация: 30.11.2021
Сообщений: 101
13.09.2023, 12:18  [ТС]
Цитата Сообщение от Uswer Посмотреть сообщение
Почитал я тему и что-то не пойму суть проблемы. LexMcLinn, допустим есть два глива "И" и "Й". Второй как бы содержит первый и при создании второго требуется наличие первого. Если проблема именно в этом, то что мешает написать класс Builder, который по запросу будет "рожать" всё что нужно?
Worldmaster, правильно обозначил путь, чтобы при создании составных глифов можно было получить элементарные последние должны иметь хоть какой-то маркер в источнике (ID). Я бы попробовал такой подход: сам глиф имеет приватный конструктор, чтобы его нельзя было родить во внешнем коде; для генерации набора глифов в буилдер (фабрику) передаём массив их маркеров; внутри буилдер генерит список глифов для каждого маркера и если он встречает составной глиф, то опираясь на маркеры нужных вложенных глифов ищет их среди уже созданных. Если в списке нет глифа с нужным маркером, то он добавляется в список. Таким образом буилдер вернёт список глифов, в котором будут все зависимые и не зависимые друг от друга глифы.
Отягощается это тем, что вдруг нужно в уже существующий Font добавить глиф. Соответственно возможность родить глиф во внешнем коде может понадобиться. Но да, получается нужно сначала отдельно вычитать из файла все необходимые вещи, создать коллекцию, добавить в глиф поле с айди из шрифта исходного, а потом уже эту красоту выплевывать во внешний код готовую и увязанную правильными ссылками.

Добавлено через 10 минут
Цитата Сообщение от Uswer Посмотреть сообщение
В моём ответе тоже, но это никак не меняет сам подход к реализации.
Я прсто о том, что реализация, если я хочу получить на выходе файл в соответствии со спецификацией otf, должна соответствовать этой спецификации. Не в смысле дать ту же структуру, хотя в итоге и это, но в смысле что объект "глиф" должен быть тем, что под ним подразумевает файл шрифта. Не буквой, не символом, а именно глифом. Символы там в другом месте, таблица *cmap, -- вот там всё про буквы. А глифы с теми буквами не соотносятся 1 к 1.
0
2298 / 1614 / 400
Регистрация: 26.06.2017
Сообщений: 4,780
Записей в блоге: 1
13.09.2023, 13:11
Цитата Сообщение от LexMcLinn Посмотреть сообщение
если я хочу получить на выходе файл в соответствии со спецификацией otf
Это уже совсем другой вопрос. Вопрос данной темы звучит иначе.
0
4 / 3 / 1
Регистрация: 30.11.2021
Сообщений: 101
13.09.2023, 15:01  [ТС]
Да блин! Там в этой таблице с глифами их может быть на законных основаниях меньше чем "количество глифов в шрифте"

Но это я уже просто жалуюсь. Пока пытаюсь что-то реализовать и до нового конкретного вопроса не доотчаялся.
0
2298 / 1614 / 400
Регистрация: 26.06.2017
Сообщений: 4,780
Записей в блоге: 1
13.09.2023, 15:27
Позволю себе продолжить тему, хотя точка вроде бы поставлена.

Не по теме:

Если что, то модератор любезно перенесёт это в другую тему.


Цитата Сообщение от LexMcLinn Посмотреть сообщение
вдруг нужно в уже существующий Font добавить глиф
Предположим что есть некий файл описывающий шрифт и мы умеет читать из него глифы при помощи фабрики. При этом также примем, что каждый глиф имеет уникальный идентификатор (маркер). Внезапно нам захотелось разработать графический редактор шрифтов [ну, а чё нет!]. И вот теперь нам надо создать новый, не существующий ранее глиф. ОК. Пользователь на основе уже имеющихся глифов создал новый и дополнил его уникальной (новой) графикой. Как это сохранить? Да всё также - передать методу класса помощника, например той же фабрики, собранный CombinedGlyph, а тот его сохранит.

Добавлено через 9 минут
LexMcLinn, я не вижу ничего страшного в том чтобы разделить логику и ответственность между разными классами. Например, класс, содержащий описанный ранее мной метод аля Build() может содержать метод типа Save(CombinedGlyph savedItem). Как именно внутри класса будет производиться сохранение в файл дело десятое, т.е. что хочу сказать - совершенно не обязательно CombinedGlyph будет отображать всю внутреннюю организацию файла шрифта, что-то может добавляться/исключаться при чтении/записи файла.
0
4 / 3 / 1
Регистрация: 30.11.2021
Сообщений: 101
13.09.2023, 20:44  [ТС]
Тут еще и область C# начинается, в которой я не супер-уверенно ся чувствую.
Я тут начал переделывать код для этих глифов и выяснил, что не совсем понимаю следующий момент:
делаю базовый класс
C#
1
2
3
4
5
6
7
8
9
10
11
abstract class GlyphA
    {
        protected uint refID;
 
        protected short lsb;
        protected short rsb;
        protected ushort advancedWidth;
 
        public abstract void Draw();
 
    }
делаю наследуемый класс:
C#
1
2
3
4
5
6
7
8
9
10
class SimpleGlyph : GlyphA
    {
        protected List<Contour> contours;
 
 
        public override void Draw()
        {
 
        }
}
И дальше у меня было свойство такое вось
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public int Xmin
        {
            get
            {
                int xMin = 0;
                if (this.contours.Count > 0) xMin = this.contours[0].GetMinX();
                if (this.contours.Count > 1)
                    for (int i = 1; i < this.contours.Count; i++)
                    {
                        if ((this.contours[i].GetMinX()) < (xMin)) xMin = this.contours[i].GetMinX();
                    }
 
                return xMin;
            }
        }
Но в абстрактный класс его положить не можно.
А оно должно гарантированно обеспечиваться всеми вариантами глифов из разных унаследованных классов.

Может я не к месту вообще применил abstract?
0
 Аватар для Worldmaster
323 / 190 / 45
Регистрация: 25.08.2011
Сообщений: 1,263
14.09.2023, 08:10
Цитата Сообщение от LexMcLinn Посмотреть сообщение
я не к месту вообще применил abstract?
Ну а действительно нафига?
Пусть будет обычный класс с виртуальными методами.
0
4 / 3 / 1
Регистрация: 30.11.2021
Сообщений: 101
14.09.2023, 08:50  [ТС]
Оказалось все можно, я не прав был, что в абстрактном класссе не бывает свойств...
C#
1
 public abstract int Xmax { get; }
просто пытался реализацию зачем-то написать в абстрактном свойстве, а нужно просто было показать что должен быть get

Добавлено через 3 минуты
Цитата Сообщение от Worldmaster Посмотреть сообщение
Ну а действительно нафига?
Пусть будет обычный класс с виртуальными методами.
Вот это для меня покамест довольно туманная материя. Где нужен абстракт, а где виртуальный, где весь класс, а где только поля ... я не имею четкого представления.

Говорили ранее про фабрики, а по примерах всех в умных книжках реализуют в таких случаях родительский класс как абстрактный, де мол объекты-то все будут создаваться в унаследованных классах, а базовый он не должен использоваться чтобы объект создавать.

Добавлено через 24 минуты
А вообще насколько грамотно делать так:
в одном наследующем классе объявляется свойство типа public int NumOfContours{get num}
в другом -- public int NumOfGlyphs {get num}

а во внешнем коде приходится разводить if(typeof(baseclassEx) == typeof(InheritedClass1..2..3) )
0
2298 / 1614 / 400
Регистрация: 26.06.2017
Сообщений: 4,780
Записей в блоге: 1
14.09.2023, 09:01
Цитата Сообщение от LexMcLinn Посмотреть сообщение
в таких случаях родительский класс как абстрактный
Абстрактный класс в данном случае можно воспринимать как некий контракт типа "вот это вот должно быть по любому". В случае фабрики это пожалуй самый удобный вариант, т.к. внутри фабрики будет создаваться список List<GlyphA>, в который можно добавить любой объект (глиф) унаследовавший/реализующий GlyphA, т.е. и SimpleGlyph и CombinedGlyph.

Добавлено через 4 минуты
Цитата Сообщение от LexMcLinn Посмотреть сообщение
А вообще насколько грамотно делать так:
Всё зависит от задачи. Зачем, например, классу SimpleGlyph свойство NumOfGlyphs? Оно ему не нужно.

Добавлено через 2 минуты
LexMcLinn, почитайте ещё и о interface, тоже весьма полезная штука. Вообще рекомендуется писать с интерфейсами.
1
4 / 3 / 1
Регистрация: 30.11.2021
Сообщений: 101
15.09.2023, 07:53  [ТС]
Ии эта штука у меня не поехала на преобразовании типов.
Что-то я делаю неправильно.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Glyph glyf;
 
public FormGlyfNew(Glyph gl)
        {
            InitializeComponent();
            glyf = gl;
 
            if (glyf is SimpleGlyph)
            {
               
                if(glyf.GetContours.Count > 0)
                {
                    tscbContour.SelectedIndex = tscbContour.Items.Count - 1;
                    ucp.SelectedContour = tscbContour.Items.Count - 1;
                }
            }
       }
он ругается что класс Glyph не содержит метода GetContours;
но он его и не содержит, такой метод есть только у SimpleGlyph:Glyph
проблема скорее в инкапсуляции неприличной, или в том что я как-то неправильно использую as/is?

Добавлено через 11 минут
И вот так тоже ругается
C#
1
2
3
4
5
6
7
public FormGlyfNew(Glyph gl)
        {
            InitializeComponent();
 
            if (gl.GetType() == typeof(SimpleGlyph))
                glyf = gl as SimpleGlyph;
}
0
 Аватар для Worldmaster
323 / 190 / 45
Регистрация: 25.08.2011
Сообщений: 1,263
15.09.2023, 07:57
Цитата Сообщение от LexMcLinn Посмотреть сообщение
неправильно использую as/is

C#
1
2
3
4
5
6
7
8
9
if (glyf is SimpleGlyph sgl)
            {
               
                if(sgl.GetContours.Count > 0)
                {
                    tscbContour.SelectedIndex = tscbContour.Items.Count - 1;
                    ucp.SelectedContour = tscbContour.Items.Count - 1;
                }
            }
1
4 / 3 / 1
Регистрация: 30.11.2021
Сообщений: 101
15.09.2023, 08:00  [ТС]
Аа, то есть переменной на уровне формы сначала присвоить значение входящей переменной, а потом ее перед действиями, относящимися только к одному из типов переводить в третью переменную конкретного типа уже...
Спасибо.
0
2298 / 1614 / 400
Регистрация: 26.06.2017
Сообщений: 4,780
Записей в блоге: 1
15.09.2023, 08:05
Это называется шаблон объявления.
0
4 / 3 / 1
Регистрация: 30.11.2021
Сообщений: 101
15.09.2023, 14:49  [ТС]
Цитата Сообщение от Uswer Посмотреть сообщение
LexMcLinn, почитайте ещё и о interface, тоже весьма полезная штука. Вообще рекомендуется писать с интерфейсами.
Насколько я понимаю концепт interface -- он не выглядит для меня как что-то большее, чем спецификация для класса

то есть я просто помечаю класс К интерфейсом IМожетОтображатьсяЮзерКонтролом№274 для того чтобы компилятор напомнил мне, что этот класс должен реализовывать все фичи, которые нужны в этом контроле, ну и чтобы вместо конкретного класса в конструкторе юзверьконтрола написать переменную с типом IМожетОтображатьсяЭтимЮзерКонтролом объект.

Другого значения интерфейса я пока не постиг, потому вижу его необходимость только когда есть несколько классов, у которых должно быть что-то общее в функционале, но через наследование это реализовывать нехорошо или невозможно (ну типа наследование от многих классов не так хорошо пишется, как реализация в классе десятка интерфейсов).
0
2298 / 1614 / 400
Регистрация: 26.06.2017
Сообщений: 4,780
Записей в блоге: 1
15.09.2023, 15:01
Применительно к вашей задаче использование абстрактного класса мне видится наиболее выгодным решением, т.к. он описывает базовую функциональность класса, т.е. всех глифов, а не лишь обозначает её, как в случае интерфейса. Тут я с вами согласен. Но если появится глиф не наследующий базовый, то только через интерфейс можно будет собрать их в кучу. Тут коротко и ясно это объясняется.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
15.09.2023, 15:01

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

Как сделать, чтобы производный класс наследовал все операторы от родительского класса и от родительского родительского
Есть 1й базовый класс в кот. определён operator ++ (); //prefix Есть производный от 1го, 2й класс в кот. дополнительно определён operator...

Класс содержащий объекты другого класса
Наткнулся на такую ситуацию. Как одно поле класса делают объект другого класса со своим конструктором. Типа class second { ...

Указатель на объект класса в классе с методом класса обращающимся к элементам класса что указан по указателю
Нужно сделать класс у которого в свойствах устанавливается через метод указатель на другой объект класса. #include &lt;iostream&gt; ...

Как связать сигнал одного класса со слотом другого класса, содержащего указатель на объект этого класса?
Подскажите, пожалуйста, как связать сигнал одного класса со слотом другого класса, содержащего указатель на объект этого класса. Буду очень...


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

Или воспользуйтесь поиском по форуму:
35
Ответ Создать тему
Новые блоги и статьи
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru