yigal_s: (Default)
[personal profile] yigal_s
Действительно, надо на время забросить расистский, шовинистический, антисемитский и всякий другой необщепринятый, хотя и небесполезный в нашем нетривиальном мире, дискурс, и попинать немножко ногами что-нидь из программирования. Пинать я буду не голословно, а приводя малоизвестные и интересные (очень надеюсь) примеры.

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

Теперь к конкретным примерам.

Когда программист "наследует" класс A от класса Base, он как бы говорит как минимум две вещи сразу. Во-первых, он говорит, что класс A - это частный случай, разновидность, субкласс класса Base (как, к примеру, учитель - частный случай человека), всё, что можно сделать с классом Base, можно сделать и с классом A, везде, где используется класс Base, можно использовать и экземпляр класса А. Во-вторых, он говорит, что имплементация класса A использует имплементацию класса Base. Тоже немаловажно - уж кто из нас не расширял функциональность класса, наследуя от неё новую, более продвинутую функциональность, использующую и старую.

Так вот, всё это очень спорная практика.

Поскольку уже в самых основах можно видеть, что подобное "двойное" наследование в одну сторону вовсе не всегда то, что нужно. Рассмотрим, к примеру, в качестве такой "основы" тип действительных и комплексных чисел. Ясно совершенно, что действительное число - частный случай комплексного. Поэтому, если оформлять их в виде классов, то действительный тип должен наследовать комплексный. Именно так и не иначе. Комплексный тип - базовый. А вот с имплементацией всё ровно наоборот, разумеется, - комплексный тип, скорее уж, использует имплементацию действительного типа (что, впрочем, в данном случае разумнее оформить не через наследование имплементации "в другую сторону", но это частности).

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

Хотя квадрат и является разновидностью прямоугольника (не говоря уже о том, что и ромба тоже), поспешно было бы наследовать квадрат от прямоугольника. И проблема тут даже не в том, что квадрату вовсе не нужно, как прямоугольнику, хранить и длину и ширину (мы уже обсудили абзацем выше, что не всегда направление наследования интерфейса и направление наследования имплементации совпадают). Проблема здесь в том, что прямоугольник в программировании и прямоугольник в математике вовсе не одно и то же. Как уже было сказано в прошлых постах ЖЖ, в математике "нет оператора присваивания", нет переменных. В програмировании же всё с точностью до наоборот. И если у нашего прямоугольника имеется метод
void Scale(real factorX, real factorY); ,
растягивающий его по ширине и высоте, то квадрат этот метод уже никак (адекватным образом) имплементировать не сможет. Неконстантный квадрат - вовсе не частный случай неконстантного прямоугольника.

[* Конец гона *]

А вот завтра пойду на работу и опять чего-нибудь унаследую.

Date: 2004-05-29 11:34 am (UTC)
From: [identity profile] dorimena.livejournal.com
а если я тут разгуляюсь с RPG ?

Date: 2004-05-29 11:40 am (UTC)
From: [identity profile] dorimena.livejournal.com
а я - болеутоляющих таблеток ))