По умолчанию любой вновь описанный метод становится статическим. Особенность такого метода заключается в его адресации. Она осуществляется еще на стадии компиляции и компоновки проекта и будет неизменна (статична) до момента новой компиляции. Статическое связывание (Static binding) обладает существенным преимуществом над всеми остальными видами адресации, поскольку обеспечивает самую высокую скорость вызова. Но рука об руку с этим преимуществом шагает и убийственный недостаток фиксированной адресации: статические методы не подлежат изменениям в компонентах-потомках.
Рассмотрим пример с гипотетическим классом TAnimal и его наследником TDog. В каждом из классов объявлен статический метод Run().
type TAnimal = class procedure Run;
end;
type TDog = class(TAnimal) procedure Run;
end;
В результате выполнения сообщается, чей метод «побежал»:
procedure TAnimal.Run; begin
ShowMessage('TAnimal.Run'); end;
procedure TDog.Run; begin
ShowMessage('TDog.Run'); end;
Посмотрим, как классы TAnimal и TDog работают в обычном проекте. Нижеприведенный пример иллюстрирует особенности вызова статического метода. Обратите внимание на второй вызов метода Animal.Run. Здесь объект Animal создан на базе объекта класса TDog, но, несмотря на это, вызов метода реализуется как Run() для класса TAnimal. Это объясняется тем, что в секции var объектная переменная Animal объявлена как переменная класса TAnimal.
var
Animal: TAnimal; Dog: TDog;
begin
Animal := TAnimal.Create;
Animal.Run; // вызов метода TAnimal.Run
Animal.Destroy;
Вывод: при вызове статических методов выбор процедуры или функции определяется исключительно типом объектной переменной (в нашем случае Animal: TAnimal). То, что объект создан на основе класса TDog, никакого значения не имеет. Компилятор все равно вызовет статический метод для класса
TAnimal.
Если класс-наследник порожден от базового класса, то дочерний класс не сможет переопределить действия статических методов своего родителя. Следовательно, будет утрачена одна из основ ООП - полиморфизм.