В Delphi методы должны объявляться внутри класса, а описываться - вне класса, при этом перед именем метода пишется имя класса с последующей точкой:
type Person = class private nm: string; // имя ag: integer; // возраст procedure SetAge(ag: integer); public constructor Create(nm: string; ag: integer); property Name: string read nm; property Age: integer read ag write SetAge; end; constructor Person.Create(nm: string; ag: integer); begin Self.nm := nm; Self.ag := ag; end; procedure Person.SetAge(ag: integer); begin if ag<0 then ag := 0; Self.ag := ag; end;
Удобен ли такой метод? Несомненно: при взгляде на класс сразу виден его интерфейс. А реализация дана ниже. Если класс находится в модуле, то его интерфейс помещается в интерфейсную секцию модуля, а реализация методов - в секцию реализации модуля.
Немного раздражают лишние детали: например, для использования класса достаточно знать его открытый интерфейс и вовсе не нужно знать, какие методы используются для чтения и записи свойств. То есть в идеале для пользователя класс должен предстать в следующем обличье:
type Person = class public constructor Create(nm: string; ag: integer); property Name: string read; property Age: integer read write; end;
В Java и C# принято прямо противоположное решение: все методы определяются только внутри интерфейса класса. Например, тот же класс на C# будет описываться так:
При таком способе все описывается сразу, что очень удобно, но есть две проблемы. Во-первых, интерфейс класса становится труднообозримым. Во-вторых, трудно перемещаться по большому классу в 200-300-1000 строк в поисках нужного метода. Обе проблемы решаются специальными средствами оболочки, позволяющимися вычленять из класса его интерфейс и перемещаться к нужному методу.
В C++ принято демократичное решение: методы могут описываться как внутри, так и вне класса. Это очень удобно: мелкие методы реализуются на месте, более крупные выносятся вовне чтобы не захламлять интерфейс класса.
В PascalABC.NET принято такое же демократическое решение: методы можно определять как внутри, так и вне интерфейса класса. Например, код нашего класса можно записать следующим образом:
type Person = class private nm: string; // имя ag: integer; // возраст procedure SetAge(ag: integer); begin if ag<0 then ag := 0; Self.ag := ag; end; public constructor Create(nm: string; ag: integer); begin Self.nm := nm; Self.ag := ag; end; property Name: string read nm; property Age: integer read ag write SetAge; end;
Конечно, наследуются недостатки обоих способов. Но есть и преимущества. Они просты.
1. При начальном обучении классам достаточно сказать, что класс - это всего лишь оболочка над переменными и подпрограммами, объединяюшая их в единое целое (пренебрежем защитой данных и явным конструктором):
type Person = class // оболочка Name: string; Age: integer; procedure Print; begin writeln(Name,' ',Age); end; end;
Это целое является типом, которым можно пользоваться как обычным типом: описывать переменные этого типа (объекты) и пользоваться ими, используя точечную нотацию для вызова этих подпрограмм (методов) и обращения к этим переменным (полям). Только сконструировать эту переменную надо перед первым использованием:
var p: Person := new Person; // Сконструировать новый объект - обязательно p.Name := 'Иванов'; p.Age := 18; p.Print;
Все просто. Такой способ изложения позволяет рассказывать о классах практически сразу после темы "Подпрограммы".
Еще можно добавить, что внутри класса можно написать свой метод-конструктор с параметрами:
constructor (nm: string; ag: integer); begin Name := nm; Age := ag; end;
Да-да, в PascalABC.NET имя можно не добавлять. Но если уж добавили - помните: все конструкторы в PascalABC.NET должны именоваться Create. Тогда предыдущий код упростится:
var p: Person := new Person('Иванов',18); p.Print;
2. При написании кода программы на доске (да-да, еще кое где все еще пишут на доске!) гораздо проще описывать методы класса сразу.
И еще одно маленькое замечание. Если уж так страшно использовать конструкторы классов, можно воспользоваться записями - в PascalABC.NET в записях тоже могут быть методы и они могут описываться внутри. Повторим предыдущий ко для записей для лучшей обозримости:
type Person = record Name: string; Age: integer; procedure Print; begin writeln(Name,' ',Age); end; end; var p: Person; begin p.Name := 'Иванов'; p.Age := 18; p.Print; end.
01.02.24. На ресурсе Stepik в ознакомительном режиме открыт курс "PascalАВС.NЕТ: продвинутый уровень".
10.07.23. Вышел релиз версии PascalABC.NET 3.9.0. Нововведения описаны здесь.
20.05.23. На странице https://pascalabc.net/stepikcourse опубликованы новые курсы по PascalABC.NET от центра олимпиадного программирования DL Club.
08.05.23. Вышла версия PascalABC.NET 3.9.0.beta. Основное - ковариантные параметры обобщений, аргументы по умолчанию при вызове подпрограммы, модуль автоматической проверки LightPT.
22.02.23. Открыта регистрация на конференцию «Использование системы программирования PascalABC.NET в обучении программированию»