Раннее связывание против позднего связывания
Различие между вызовом статического метода и динамического метода является различием между решением сделать немедленно и ре- шением отложить. Когда вы кодируете вызов статического метода, вы по существу говорите компилятору; "Ты знаешь, чего я хочу. Пойди и вызови это." С другой стороны, применение вызова виртуального метода, подобно разговору с компилятором; "Ты не знаешь пока, че- го я хочу. Когда придет время, задай вопрос о конкретном экземп- ляре."
Подумайте об этой метафоре в терминах проблемы MoveTo, упо- мянутой в предыдущем разделе. Вызов TBee.MoveTo может привести только к одному - выполнению MoveTo, ближайшей в объектной иерар- хии. В этом случае TBee.MoveTo по-прежнему будет вызывать опреде- ление MoveTo для TWinged, так как TWinged является ближайшим к TBee типом вверх по иерархии. Если предположить, что не определен никакой дочерний тип, который определяет собственный метод MoveTo, переопределяющий MoveTo типа TWinged, то любой порожден- ный по отношению к TWinged тип будет по-прежнему вызывать тот же самый экземпляр метода MoveTo. Решение может быть принято во вре- мя компиляции и это все, что должно быть сделано.
Однако совсем другое дело, когда метод MoveTo вызывает Show. Каждый тип фигуры имеет свой собственный экземпляр Show, поэтому то, какой экземпляр Show вызывается методом MoveTo, полностью за- висит от того, какая реализация объекта вызывает MoveTo. Именно поэтому решение о вызове метода Show внутри экземпляра MoveTo должно быть отложено: при компиляции кода MoveTo не может принято никакого решения относительно того, какой метод Show должен быть вызван. Эта информация недоступна во время компиляции, поэтому решение должно быть отложено до тех пор, пока программа не начнет выполняться, и пока нельзя будет запросить экземпляр объекта, вы- зывающий MoveTo.
Процесс, с помощью которого вызовы статических методов од- нозначно разрешаются компилятором во время компиляции в один ме- тод, называется ранним связыванием. При раннем связывании вызыва- ющий и вызываемый методы связываются при первой же возможности, т.е. во время компиляции. При позднем связывании вызывающий и вы- зываемый методы не могут быть связаны во время компиляции, поэто- му включается механизм, позволяющий осуществить связывание нес- колько позднее, когда вызов действительно произойдет.
Сущность механизма интересна и тонка, и немного позднее вы увидите, как он работает.