Эта статья посвящена созданию модели данных, которая красиво ложилась бы на SQL и содержала в себе «правильное» ООП наследование. Надо сказать, что эта задача возникала у меня в разное время на разных проектах, и решалась она там тоже по-разному. Названия подходов взяты из сложившейся на соответствующих проектах терминологии.
Читать полностью »
Рубрика «наследование» - 3
Реализация ООП-наследования в классах, работающих с SQL и MS Entity Framework
2017-02-26 в 10:00, admin, рубрики: .net, C#, entity framework, sql, наследование, оопКомпозиция и интерфейсы
2016-11-02 в 10:52, admin, рубрики: .net, C#, extension methods, java, интерфейсы, композиция, методы расширения, наследование, ооп, Проектирование и рефакторингВ мире объектно-ориентированного программирования уже достаточно давно подвергается критике концепция наследования.
Аргументов достаточно много:
- дочерний класс наследует все данные и поведение родительского, что нужно не всегда (а при доработке родительского в дочерний класс вообще попадают данные и поведение, которые не предполагались на момент разработки дочернего);
- виртуальные методы менее производительные, а в случае, если язык позволяет объявить невиртуальный метод, то как быть, если в наследнике нужно его перекрыть (можно пометить метод словом new, но при этом не будет работать полиморфизм, и использование такого объекта может привести к не ожидаемому поведению, в зависимости от того, к какому типу приведен объект в момент его использования);
- если возникает необходимость множественного наследования, то в большинстве языков оно отсутствует, а там, где есть (C++), считается трудоемким;
- есть задачи, где наследование как таковое не может помочь — если нужен контейнер элементов (множество, массив, список) с единым поведением для элементов разных типов, и при этом нужно обеспечить статическую типизацию, то здесь помогут обобщения (generics).
- и т.д., и т.п.
Альтернативой наследованию являются использование интерфейсов и композиция. (Интерфейсы давно используется в качестве альтернативы множественному наследованию, даже если в иерархии классов активно используется наследование.)
Декларируемым преимуществом наследование является отсутствие дублирования кода. В предметной области могут встречаться объекты с похожим или одинаковым набором свойств и методов, но имеющих частично или полностью разные поведение или механизмы реализации этого поведения. И в этом случае для устранения дублирование кода придется использовать иные механизмы.
А как можно решить эту задачу (отсутствие дублирования кода) в случае композиции и интерфейсов?
Этой теме и посвящена настоящая статья.
Читать полностью »
Наследование ActiveRecord’s, описывающих одну таблицу (паттерн single table inheritance) в Yii2
2016-01-12 в 11:22, admin, рубрики: active record, php, yii, yii2, наследованиеВ большинстве реляционных баз данных, к сожалению, нет поддержки наследования, так что приходится реализовывать это вручную. В этой статье я хочу кратко показать, как реализовать такой подход к наследованию, как «single table inheritance», описанный в книге «Patterns of Enterprise Application Architecture» by Martin Fowler.
В соответствии с этим паттерном, нужно использовать общую таблицу для наследуемых моделей и в этой таблице добавить поле type
, которое будет определять класс-наследника этой записи.
В этой статье будет использоваться следующая структура наследования моделей:
Car
|- SportCar
|- HeavyCar
Таблица `car`
имеет следующую структуру:
CREATE TABLE `car` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`type` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
);
INSERT INTO `car` (`id`, `name`, `type`) VALUES (1, 'Kamaz', 'heavy'), (2, 'Ferrari', 'sport'), (3, 'BMW', 'city');
Модель Car
можно сгенерировать с помощью Gii.
Читать полностью »
Hibernate: ленивая загрузка, наследование и instanceof
2015-02-16 в 16:02, admin, рубрики: hibernate, instanceof, java, наследование, ооп, слои абстракцийРассмотрим, в качестве примера, следующую ситуацию. У нас имеется класс User с полями, описывающими пользователя. Имеется класс Phone, который является родительским для классов CellPhone и SatellitePhone. В классе User есть поле содержащее список телефонов пользователя. В целях уменьшения нагрузки на БД мы сделали этот список «ленивым». Он будет загружаться только по требованию.
public class User {
...
@OneToMany(fetch = FetchType.LAZY)
private List<Phone> phones = new ArrayList<Phone>();
public List<Phone> getPhones() {
return phones;
}
}
public class Phone {
...
}
public class CellPhone extends Phone {
...
}
public class SatellitePhone extends Phone {
...
}
В такой конфигурации при запросе списка телефонов конкретного пользователя мы можем получить как список проинициализированных объектов-телефонов (например, если они уже есть в кэше), так и список proxy-объектов.
В большинстве ситуаций нам не важно с чем именно мы работаем (реальным объектом или его proxy). При запросе какого-либо поля какого-либо объекта — proxy-объект автоматически проинициализируется, и мы получим ожидаемые данные. Но если нам нужно узнать тип объекта, то все идет наперекосяк.
Читать полностью »
Краткая заметка про наследование в Node.js
2015-01-05 в 4:43, admin, рубрики: class, inherit, inheritance, inherited, javascript, node.js, override, класс, наследование, оопВ JavaScript существует множество разных способов наследования, классового и прототипного, фабричного и через примеси, прямого и непрямого, а так же гибриды нескольких методов. Но у Node.js есть его родной способ с применением util.inherits(ChildClass, ParentClass). До недавнего времени я использовал нодовский способ только для встроенных классов (когда нужно сделать своего наследника для EventEmitter, Readable/Writable Stream, Domain, Duffer и т.д.), а для моделирования предметной области применял общеупотребительные для всего JavaScript практики. И вот, впервые, понадобилось реализовать собственную иерархию системных классов, не наследников от встроенных, но и не классов предметной области, а классов, массово поражаемых в системном коде сервера приложений Impress. И простого использования util.inherits уже как-то не хватило, поискал я статьи и не найдя полностью всего, что мне нужно, изучил примеры наследования в исходниках самой ноды, подумал и сделал пример родного нодовского наследования себе на память и написал эту небольшую заметку, чтобы она, надеюсь, помогла еще и вам. Сразу предупреждаю, что реализация вызова метода родительского класса из переопределенного в дочернем классе метода, мне не очень нравится из-за громоздкости, поэтому, приветствую альтернативные способы и приглашаю коммитить их в репозиторий или в комментарии к этой заметке.
Ответ на Решетчатое наследование
2014-11-26 в 13:38, admin, рубрики: иерархия, композиция, наследование, ненормальное программирование, ооп Эта публикация — ответ на текст «Решетчатое наследование», опубликованный хабрапользователем potan, с предложением альтернативы, на субъективный взгляд автора, более близкой к ООП с классами.
Читать полностью »
Решетчатое наследование
2014-11-26 в 7:23, admin, рубрики: clojure, иерархии, наследование, ненормальное программирование, ооп Наследование, при кажущейся простоте, часто приводит к сложным, сопротивляющимся изменениям структурам. Иерархии классов растут как самый настоящий лес.
Целью наследование является привязка кода (набора методов) к минимальному набору свойств сущности (как правило — объекта), которые он обеспечивает и которые ему требуются. Это упрощает повторное использование, тестирование и анализ кода. Но наборы свойств со временем становятся очень большими, начинают пересекаться нетривиальным образом. И в структуре классов появляются миксины и прочее множественное наследование.
Внести изменения в глубине иерархии становится проблематично, приходится думать заранее о «внедрении зависимостей», разрабатывать и использовать сложные инструменты рефакторинга.
Возможно ли всего этого избежать? Стоит попытаться — пусть методы будут привязаны к множеству характерных свойств объекта (тегов), а иерархия наследования выстраивается автоматически по вложенности этих множеств.
Пусть мы разрабатывает иерархию для игровых персонажей. Часть кода будет общая для всех персонажей — она привязана к пустому набору свойств. Код, отвечающий за их отображение будет представлен в виде вариантов для OpenGL и DirectX разных версий. Что-то будет зависеть от расы персонажа, что-то от наличия и вида магических способностей и тп. Теги персонажа первичны. Они перечисляются явно, а не наследуются. А реализация наследуется в зависимости от набора тегов (по вложенности). Таким образом умение стрелять из ПЗРК не окажется у кенгуру, потому что его унаследовали от пехотинца.
Идея такого подхода была предложена Дмитрием Кимом. Автор не стал ее воплощать в код, я попробую исправить это упущение.
Реализация такого подхода на Clojure, как обычно, на github.
Читать полностью »
Краткий конспект по языку JavaScript
2014-11-17 в 11:48, admin, рубрики: javascript, strict mode, наследование, объектыЯ —.NET разработчик. Но в последнее время всё чаще сталкиваюсь с JavaScript. Причём, процентах в 50 случаев, я что-то на нём пишу, в остальных 50 — разбираюсь с чужим кодом, да ещё и прошедшим через минификацию, а иногда и обфускацию. В этой статье захотелось поделиться теми моментами, которые мне показались важными для понимания языка и эффективной работы с ним. Тут не будет ничего нового или неизвестного для людей, уже имевших дело с языком, и не будет чего-то такого, чего нельзя найти в других источниках. Для меня статья будет полезна как способ лучше разобраться в предмете, для читателей, я надеюсь, — как повод освежить знания.
Брендан Айк упоминал, что JavaScript был создан за 10 дней. Думаю, идея вынашивалась дольше. Как бы то ни было, язык получился и с тех пор только набирает популярность. Особенно после появления AJAX.
JavaScript — язык со слабой динамической типизацией, автоматическим управлением памятью и прототипным наследованием.
JavaScript состоит из трёх обособленных частей:
- ядро (ECMAScript),
- объектная модель браузера (Browser Object Model или BOM),
- объектная модель документа (Document Object Model или DOM).
В статье, в основном, пойдёт речь о ядре. Конечно, в примерах кода будут использоваться элементы DOM и BOM, но заострять на них внимание не буду.
Наследование комбинаторных парсеров на Julia
2014-10-28 в 11:33, admin, рубрики: Julia, Компиляторы, наследование, ненормальное программированиеКомбинаторные (монадические) парсеры достаточно хорошо известны (wikibooks). Они представляют из себя библиотеку маленьких парсеров, которые распознают простые элементы грамматики, и способы объединять несколько парсеров в один (комбинировать — от сюда и название). Монадические они потому что один из способов комбинирования, порождения парсера остатка текста на основе результата разбора начала, удовлетворяет условиям, накладываемым на математический объект «монада». В языке Haskell это позволяет воспользоваться мощным сервисом, предоставляемым языком и библиотеками. В других языках название «монадические» можно смело игнорировать — это не будет мешать их реализации и использованию, включая упомянутую выше операцию «bind».
Проще всего комбинаторные парсеры реализуются в языках с поддержкой замыканий, но можно воспользоваться и классическим ООП (пример описан Rebecca Parsons в книге Мартина Фаулера «Предметно-ориентированные языки»).
К преимуществам комбинаторных парсеров относится простота использования (запись на языке программирования практически не отличается от обычного описания грамматики), независимость от препроцессора (как yacc/bison, happy или ocamlyacc), возможность реализовать некоторые элементы, плохо укладывающиеся в контекстно-свободную грамматику, прямо на языке программирования общего назначения.
К недостаткам — сложность составления сообщений об ошибке, неспособность работать с леворекурсивной грамматикой (приводит к зацикливанию), а так же то, что очень легко сделать этот парсер не эффективным по быстродействию и памяти. (Одна из причин — компилятор не может произвести оптимизацию в терминах грамматики, так как работает на уровне языка программирования. Но есть и другие тонкости, требующие внимания, если требуется эффективность.)
Как альтернативу можно рассмотреть реализации в виде макросов (например OCaml streams parsers). В Perl6 поддержка грамматик встроена в язык.
Наследование
Персер конкретного языка состоит из множества более специализированных парсеров, ссылающихся друг на друга. В этом отношении парсеры напоминают методы некого объекта. Возникает желание порождать парсеры новых версий языков, подменяя отдельные подпарсеры (как это делается в паттерне проектирования «шаблонный метод» из ООП). Для экспериментов с этим подходом (а так же в порядке изучения очередного языка) я выбрал язык Julia — динамически-типизированном с особым подходом к наследованию (подобному CLOS из Common Lisp и R).
В отличие от обычных комбинаторных парсеров, подход с наследованием является экспериментальным (хотя в некотором виде поддерживается библиотекой макросов OCaml и языком Perl6). Пока он порождает не очень читабельный код. Исходный код доступен на Github.
Читать полностью »
Выразительный JavaScript: Тайная жизнь объектов
2014-10-27 в 8:53, admin, рубрики: javascript, инкапсуляция, наследование, объекты, полиморфизм, Программирование, форматирование таблицСодержание
- Введение
- Величины, типы и операторы
- Структура программ
- Функции
- Структуры данных: объекты и массивы
- Функции высшего порядка
- Тайная жизнь объектов
- Проект: электронная жизнь
- Обработка ошибок
- Регулярные выражения
- Модули
- Проект: язык программирования
- JavaScript и браузер
- Document Object Model
- Обработка событий
- Проект: игра-платформер
- Рисуем на Canvas
- HTTP
- Формы и поля ввода
- Проект: Paint
- Node.js
- Проект: веб-сайт по обмену умениями
- Песочница для кода
Проблема объектно-ориентированных языков в том, что они тащат с собой всё своё неявное окружение. Вам нужен был банан – а вы получаете гориллу с бананом, и целые джунгли впридачу.
Джо Армстронг, в интервью Coders at Work
Термин «объект» в программировании сильно перегружен значениями. В моей профессии объекты – стиль жизни, тема священных войн и любимое заклинание, не теряющий своей магической силы.
Стороннему человеку всё это непонятно. Начнём же с краткой истории объектов как концепции в программировании.
Читать полностью »