Объясняем наследование
От: Tilir Россия http://tilir.livejournal.com
Дата: 29.10.14 09:42
Оценка: 66 (1) -2 :)
Hi,

У меня тут есть немного студентов на нашей базовой кафедре, которых надо научить плюсам в свободное от работы время. Пока всё шло хорошо, но скоро надо будет объяснить им наследование. Пока план примерно такой:


Но весь этот план требует некоего сквозного примера для которого проводить объяснения. И вот тут у меня затык.

Все книги по C++ которые объясняют наследование вызывают желание убить себе лицо рукой. Вызывали когда я был на втором курсе, вызывают сейчас много лет спустя. Даже дедушка Строструп не уберёгся и унаследовал класс Manger от класса Employer, стыд и унижение. Варианты наследовать котят от собачек, груши от фруктов, кружочки от квадратиков и т.п. не рассматриваются, мне будет стыдно рассказывать, им будет стыдно слушать. Когда я совсем состарюсь пойду воспитателем в детский сад, там мне это очень пригодится, а пока ну нафиг.

Нахожусь в активном поиске нормального вменяемого примера наследования. Пока что придумал такую идею -- наследовать от "графа вообще" его частные случаи -- CFG, DAG, дерево. Близко к моей основной теме (оптимизирующие компиляторы), можно что-то рассказать дополнительно.

Но хотелось бы послушать мнение народа. Как бы вы объясняли наследование?

---
With best regards, Konstantin
Re: Объясняем наследование
От: Yagg Россия  
Дата: 29.10.14 10:04
Оценка: +1
Здравствуйте, Tilir, Вы писали:

T>Все книги по C++ которые объясняют наследование вызывают желание убить себе лицо рукой. Вызывали когда я был на втором курсе, вызывают сейчас много лет спустя. Даже дедушка Строструп не уберёгся и унаследовал класс Manger от класса Employer, стыд и унижение. Варианты наследовать котят от собачек, груши от фруктов, кружочки от квадратиков и т.п. не рассматриваются, мне будет стыдно рассказывать, им будет стыдно слушать. Когда я совсем состарюсь пойду воспитателем в детский сад, там мне это очень пригодится, а пока ну нафиг.


Не по теме, но, честно говоря, лучше бы студентам рассказывали более подробно про функциональную декомпозицию. Имхо, это сейчас новички не умеют делать от слова совсем. Сразу начинают лепить куда придётся эти наследования, инкапсуляции и прочие полиморфизмы, в то время как всё это стоит применять уже после проведения декомпозиции. Похоже и у дедушки Страуструпа та же проблема...
наболело
Re: Объясняем наследование
От: HrorH  
Дата: 29.10.14 11:00
Оценка: +1
Здравствуйте, Tilir, Вы писали:

T>Но хотелось бы послушать мнение народа. Как бы вы объясняли наследование?


То, что пример найти не удается, это как бы намекает на то, что Вы ищете среди примеров на наследование реализации.
Если говорить о наследовании интерфейса, пример будет легче найти, например какой-нибудь сервис, одна реализация лезет в БД, другая работает в памяти,
а интерфейс у них один и тот же. Это сплошь и рядом используется для тестирования.

Вообще я бы рассказал немного, как это сделано в других языках. Хотя бы в том же C#, там ключевое слово interface есть.
Боюсь что многочисленные тонкости C++ отвлекут внимание студентов от сути концепций...

Вообще я бы больше акцентировал внимание на виртуальных (и чисто виртуальных) методах, студенты не понимают что это и зачем нужно.
Re: Объясняем наследование
От: vpchelko  
Дата: 29.10.14 11:37
Оценка:
Здравствуйте, Tilir, Вы писали:

  Скрытый текст
T>Hi,

T>У меня тут есть немного студентов на нашей базовой кафедре, которых надо научить плюсам в свободное от работы время. Пока всё шло хорошо, но скоро надо будет объяснить им наследование. Пока план примерно такой:


T>

    T>
  • Рассказать про открытое наследование интерфейса. Показать как писать чисто абстрактные классы. Рассказать про чисто виртуальные функции.
    T>
  • Показать как удобно объекты с одним интерфейсом втыкаются в обобщенный код
    T>
  • Немного блабла про is-a и LSP
    T>
  • Упомянуть про наследование реализации, рассказать про просто виртуальные функции, статический и динамический тип, показать примеры когда это полезно и когда вредно. Особо остановиться на виртуальных деструкторах.
    T>
  • Упомянуть про закрытое и защищённое наследование. Объяснить что закрытое это такая композиция (и поэтому лучше делать явную композицию), а защищённое вообще никто не знает зачем нужно.
    T>
  • Рассказать про RTTI и dynamic_cast.
    T>
  • И дальше отправиться в космос -- множественное наследование, ромбовидные схемы, виртуальные базовые классы, etc.
    T>

T>Но весь этот план требует некоего сквозного примера для которого проводить объяснения. И вот тут у меня затык.


T>Все книги по C++ которые объясняют наследование вызывают желание убить себе лицо рукой. Вызывали когда я был на втором курсе, вызывают сейчас много лет спустя. Даже дедушка Строструп не уберёгся и унаследовал класс Manger от класса Employer, стыд и унижение. Варианты наследовать котят от собачек, груши от фруктов, кружочки от квадратиков и т.п. не рассматриваются, мне будет стыдно рассказывать, им будет стыдно слушать. Когда я совсем состарюсь пойду воспитателем в детский сад, там мне это очень пригодится, а пока ну нафиг.


T>Нахожусь в активном поиске нормального вменяемого примера наследования. Пока что придумал такую идею -- наследовать от "графа вообще" его частные случаи -- CFG, DAG, дерево. Близко к моей основной теме (оптимизирующие компиляторы), можно что-то рассказать дополнительно.


T>Но хотелось бы послушать мнение народа. Как бы вы объясняли наследование?


T>---

T>With best regards, Konstantin


В Java очень хорошо наследование показано стандартными коллекциями: List, Map, Set ... etc

А вот например С++ виртуальное наследование, я до сих пор не видел прикладных задач — где это нужно.
Сало Украине, Героям Сала
Отредактировано 29.10.2014 11:38 vpchelko . Предыдущая версия .
Re[2]: Объясняем наследование
От: Miroff Россия  
Дата: 29.10.14 12:49
Оценка:
Здравствуйте, vpchelko, Вы писали:

V>В Java очень хорошо наследование показано стандартными коллекциями: List, Map, Set ... etc


Коллекции лучше не трогать, а то придется про ко- и контрвариантность рассказывать.
Re: Объясняем наследование
От: Miroff Россия  
Дата: 29.10.14 12:54
Оценка: 5 (1)
Здравствуйте, Tilir, Вы писали:

T>Но хотелось бы послушать мнение народа. Как бы вы объясняли наследование?


Что-нибудь рассчетное, например, орбиты планет. Важно не просто наследование, в преимущества которые оно дает, в частности полиморфизм.
Re[2]: Объясняем наследование
От: Tilir Россия http://tilir.livejournal.com
Дата: 29.10.14 12:56
Оценка:
Здравствуйте, Miroff, Вы писали:

M>Что-нибудь рассчетное, например, орбиты планет. Важно не просто наследование, в преимущества которые оно дает, в частности полиморфизм.


А вы не могли бы подробней про орбиты планет? Что наследуется, какие преимущества даёт?
Re: Объясняем наследование
От: koodeer  
Дата: 29.10.14 13:16
Оценка: 2 (2) +2
Здравствуйте, Tilir, Вы писали:

T> немного студентов


T> Варианты наследовать котят от собачек, груши от фруктов, кружочки от квадратиков и т.п. не рассматриваются, мне будет стыдно рассказывать, им будет стыдно слушать.


Про кошечек и собачек может быть и стыдно, но студенты наверняка играют в игры. Вот на примере иерархии игровых объектов стратегии и можно объяснить наследование. Например, базовый класс Unit. От него наследуются всякие там танки, машины, пехота. У каждого из этих юнитов своё поведение. Подошла армия к реке — плавающие юниты двинулись вплавь, неплавающие в обход, искать брод или мост. Подошли к болоту — гусеничные ломятся напролом, колёсные в объезд. Это поведение реализовано в перегруженном виртуальном методе Move. Студентам должно быть интересно.
Re[3]: Объясняем наследование
От: Miroff Россия  
Дата: 29.10.14 13:42
Оценка: 10 (1)
Здравствуйте, Tilir, Вы писали:

T>Здравствуйте, Miroff, Вы писали:


M>>Что-нибудь рассчетное, например, орбиты планет. Важно не просто наследование, в преимущества которые оно дает, в частности полиморфизм.


T>А вы не могли бы подробней про орбиты планет? Что наследуется, какие преимущества даёт?


Например, так:

Point(x, y)
  def move(dx, dy)

CelestialBody(mass) extends Point
  def applyForce(f, dt)

Planet(radius) extends CelestialBody
  def detectCollisions(neighbors)
Re: Объясняем наследование
От: LaptevVV Россия  
Дата: 29.10.14 14:07
Оценка:
Здравствуйте, Tilir, Вы писали:
T>Но хотелось бы послушать мнение народа. Как бы вы объясняли наследование?

В качестве намека.
При реализации интерпретатора виртуальной машины систему команд удобно представлять иерархией наследования с абстрактным классом во главе.
И здесь же — паттерн Команда можно объяснять. И функтор — тоже.

В нашей среде Semantic операторы учебного языка построены в иерархию наследования на основе паттерна Наблюдатель.
Прога представляет собой многоуровневый список списков — семантическое дерево. Один оператор — это узел дерева.
Обход дерева — это Визитор.
Изменения в каком-нить узле — Наблюдатель работает.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[3]: Объясняем наследование
От: vpchelko  
Дата: 29.10.14 20:01
Оценка:
Здравствуйте, Miroff, Вы писали:

M>Коллекции лучше не трогать, а то придется про ко- и контрвариантность рассказывать.


А нафига так преподавать?

Для меня на практике, наследование — это формальность — детали реализации.

Тот же List у нас в массиве хранится (ArrayList) либо на удаленном сервере (своя реализация AbstactCollection — которая по сети данные гоняет), либо в базе данных (spring / jpa).

Ну да для конечного пользователя — это просто List — интерфейс.
Сало Украине, Героям Сала
Отредактировано 29.10.2014 20:06 vpchelko . Предыдущая версия . Еще …
Отредактировано 29.10.2014 20:03 vpchelko . Предыдущая версия .
Отредактировано 29.10.2014 20:02 vpchelko . Предыдущая версия .
Re[4]: Объясняем наследование
От: vpchelko  
Дата: 29.10.14 20:09
Оценка:
Здравствуйте, vpchelko, Вы писали:

V>Здравствуйте, Miroff, Вы писали:


M>>Коллекции лучше не трогать, а то придется про ко- и контрвариантность рассказывать.


V>А нафига так преподавать?


V>Для меня на практике, наследование — это формальность — детали реализации.


V>Тот же List у нас в массиве хранится (ArrayList) либо на удаленном сервере (своя реализация AbstactCollection — которая по сети данные гоняет), либо в базе данных (spring / jpa).


V>Ну да для конечного пользователя — это просто List — интерфейс.


А там можно перейти к прелестям Java — Proxy Injection. Которые в рантайме строят нужный нам (конфигу) объект.
Сало Украине, Героям Сала
Re[2]: Объясняем наследование
От: Artem Korneev США https://www.linkedin.com/in/artemkorneev/
Дата: 29.10.14 20:42
Оценка:
Здравствуйте, koodeer, Вы писали:

K>Про кошечек и собачек может быть и стыдно, но студенты наверняка играют в игры. Вот на примере иерархии игровых объектов стратегии и можно объяснить наследование. Например, базовый класс Unit. От него наследуются всякие там танки, машины, пехота. У каждого из этих юнитов своё поведение. Подошла армия к реке — плавающие юниты двинулись вплавь, неплавающие в обход, искать брод или мост. Подошли к болоту — гусеничные ломятся напролом, колёсные в объезд. Это поведение реализовано в перегруженном виртуальном методе Move. Студентам должно быть интересно.


Присоединюсь к предложению рассказывать на примере RTS-игры.
Я именно так и объяснял когда-то стажёрам, нафига нужны виртуальные функции. Когда выделяем мышкой группу объектов — мы получаем коллекцию с указателями на объекты разных классов. Все они реализуют один и тот же интерфейс, но реализуют его каждый по-своему.
С уважением, Artem Korneev.
Re: Объясняем наследование
От: Abyx Россия  
Дата: 29.10.14 20:45
Оценка:
Здравствуйте, Tilir, Вы писали:

y STLа классы называются meow и purr, при этом он офигенно крут, и объясняет вещи нормально.
In Zen We Trust
Re[2]: Объясняем наследование
От: Tilir Россия http://tilir.livejournal.com
Дата: 29.10.14 20:47
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>При реализации интерпретатора виртуальной машины систему команд удобно представлять иерархией наследования с абстрактным классом во главе.


Слишком тонкий намёк, хотелось бы чуть подробней.

class Mov : public Mnemonic {.....};
class Jmp : public Mnemonic {.....};


Но какие могут быть методы у "Мнемоники вообще"? Там даже execute будет с разным числом параметров.

До паттернов пока рано. Когда начинаются шаблоны я возможно упомяну паттерны и их реализацию метапрограммами Александреску-стайл, но мне кажется это слишком разрушительно. Пока что речь всего лишь о наследовании.
Re[2]: Объясняем наследование
От: Tilir Россия http://tilir.livejournal.com
Дата: 29.10.14 21:00
Оценка: +1
Здравствуйте, Abyx, Вы писали:

A>y STLа классы называются meow и purr, при этом он офигенно крут, и объясняет вещи нормально.


Лававеевские подкасты это плюсовое безумие, рассчитанное на расширение кругозора профессионалов.

template<class U>
struct purr < U, enable_if<std::is_integral<U>::value > > {};


Хм. Ну да. Purr.

Близкий аналог -- известная книга Дона Бокса про COM Internals, где кокласс Горилла маршалит экземпляр банана. Меня всегда несколько раздражали эти ужимки и прыжки. Да, профи через кисок продерётся и мессадж поймёт. Но 9/10 дропнут на середине. Ибо от кисок -- тошнит. Программист всё-таки занят делом, по большей части -- серьёзным и полезным.
Re[2]: Объясняем наследование
От: Tilir Россия http://tilir.livejournal.com
Дата: 29.10.14 21:05
Оценка:
Здравствуйте, koodeer, Вы писали:

K> Например, базовый класс Unit.


Какие методы можно унаследовать из базового класса Unit?
Re[3]: Объясняем наследование
От: Abyx Россия  
Дата: 29.10.14 21:06
Оценка: :)))
Здравствуйте, Tilir, Вы писали:

T>Ибо от кисок -- тошнит. Программист всё-таки занят делом, по большей части -- серьёзным и полезным.


Ты просто ненавидишь котиков.
In Zen We Trust
Re[2]: Объясняем наследование
От: Tilir Россия http://tilir.livejournal.com
Дата: 29.10.14 21:10
Оценка:
Здравствуйте, vpchelko, Вы писали:

V>В Java очень хорошо наследование показано стандартными коллекциями: List, Map, Set ... etc


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

Как раз на примере vector, map, set, etc я объясняю случаи когда нужно обходиться без наследования.
Re[3]: Объясняем наследование
От: vpchelko  
Дата: 29.10.14 21:20
Оценка:
Здравствуйте, Tilir, Вы писали:

T>Как раз на примере vector, map, set, etc я объясняю случаи когда нужно обходиться без наследования.


Обоснуй

T> ортогональные алгоритмы и контейнеры


По подробнее, я не знаю таких терминов.

T> Там дикий оверхед на виртуальные вызовы и марсианские требования к тому что и как туда можно класть.


Это вы о чем вообще?


П.с. в Java например: есть TreeMap (эквивалент std::map), HashMap, ConcurentTreeMap ConcurentHashMap. У каждой реализации есть свои преимущества. и они реализуют одну суть — ассоциативный массив.
Сало Украине, Героям Сала
Отредактировано 29.10.2014 21:32 vpchelko . Предыдущая версия . Еще …
Отредактировано 29.10.2014 21:28 vpchelko . Предыдущая версия .
Отредактировано 29.10.2014 21:27 vpchelko . Предыдущая версия .
Отредактировано 29.10.2014 21:26 vpchelko . Предыдущая версия .
Отредактировано 29.10.2014 21:25 vpchelko . Предыдущая версия .
Отредактировано 29.10.2014 21:21 vpchelko . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.