September 14, 2006

Виртуальные методы

Oldnewthing размышляет на тему виртуальных методов.

Техническая сторона вопроса понятна. В данном случае речь идёт о философской стороне. Всё сводится к тому, что автор класса, объявляющего виртуальные методы, никак не может влиять на классы-наследники и их поведение, но может зависеть от них. Хорошо когда ты сам автор и базового и дочернего классов. Но в случае написания очередной библиотеки, в конце концов придётся оставить что-то на доработку пользователям, то есть публиковать точки расширения (extensibility points).

Есть несколько различных подходов к решению проблемы. Самый прстой - запретить публичные виртуальные методы. Подход хорош, но как же быть с расширяемостью? Через callbacks? Может быть. Кстати, в скриптовых ОО языках, таких как Python и Ruby все методы по умолчанию являются виртуальными. Там ситуация ещё сложнее :-) и данный подход не применим в принципе.

Для расширяемости можно предложить и другие варианты. Например, те же callback'и или, в случае с .net, events. Но и здесь возможны способы, когда плохой пользователь всё испортит.

Можно использовать COM-подход: наследование интерфейса, а не реализации. Создаётся интерфейс и какое-то количество его реализаций. Эти реализации пишутся автором, то есть тут не может быть разговора о неправильном использовании виртаульных методов. Конкретные реализации должны быть окончательными (final в Java или sealed в С#), а значит, запрещать наследование (к сожалению не в каждом языке есть такая возможность). А вот создавать новые реализации данного интерфейса -- сколько угодно. Вроде бы всё хорошо. Создатель класса не полагается на кривую реализацию пользователя.

Но не тут-то было! В любом из приведённых решений пользователь может очень просто всё испортить. Достаточно просто в методе выполнить совсем не те действия, которые от него ожидаются. То есть, по сути, нарушить контракт. И тогда уж ничего не поделаешь. Получается что всё зависит от "чистоплотности" пользоватлеля, который решился на расширение функциональности класса через предоставляемые extensibility points. А расширяемость просто необходима в некоторых случаях. Совсем другое дело, что иногда её можно избежать.

tags: ,


Comments: Post a Comment



<< Home

This page is powered by Blogger. Isn't yours?