Мне кажется, что я своим начальным постом ввёл кого-то в заблуждение тем, что там в примерах методы определяются сразу внутри объектов. Приношу свои извинения, тема не об этом, а лишь о разделение объекта на публичную и приватную части.
В первом посте я описал каким бы мог быть паскаль в параллельной вселенной, а сейчас я попробую выдвинуть некоторое конкретное предложение.
МотивацияИзначально секция interface задумывалась как секция, в которой описаны только публичные объявления для клиентского кода. К сожалению, с введением ООП сложилась практика программирования, нарушающая эту задумку, т.к. любой публичный объект должен быть полностью объявлен в interface-секции, вместе со всеми приватными составляющими. Хуже того, вслед за объектом часто приходится выносить в интерфейсную часть вспомогательные типы, константы и другие объекты, которые не должны быть видны в клиентском коде.
Решением данной проблемы мог бы являться другой подход к дизайну языка, когда публичная часть объекта объявляется в interface-секции, а приватная — в implementation-секции. Здесь я попытаюсь описать как в текущий синтаксис встроить такую возможность, не ломая совместимость со старым кодом.
Ключевое слово forwardЛюбые объекты, записи, классы (и, возможно, дженерики) в интерфейсной части можно объявить с пометкой forward:
- Код: Выделить всё
- type
 TMyObject = forward object
 ...
 end;
 
Понимать его следует так, что объект объявлен не полностью, и у него (обязательно) есть продолжение в секции реализации.
Вложенные типы тоже могут быть с пометкой forward, но только если внешний тип имеет пометку forward:
- Код: Выделить всё
- type
 TMyClass = forward class
 type
 // Так можно — внешний класс тоже неполный
 TMyObject = forward object
 ...
 end;
 ...
 end;
 
 TMyObject = object
 type
 // А вот так нельзя — неполный класс внутри полного
 TMyClass = forward class
 ...
 end;
 ...
 end;
 
Ключевое слово нужно по следующей причине. Если бы его не было, то человек, привыкший к текущему паскалю, может по ошибке принять объявление неполного объекта как полного, что введёт его в заблуждение. Пометка forward вносит ясность, говорит что перед нами не полное описание объекта и что-то ещё объявлено в секции реализации.
Возможно, что слово forward является не самым подходящим и корректным. Я его взял из текущей возможности предварительного объявления функций и процедур.
ВидимостьОбщие правила видимости сохраняются. Объявления выше видны, объявления ниже — нет:
- Код: Выделить всё
- unit MyUnit;
 
 interface
 
 type
 TMyObject = forward object
 strict protected
 function Y: LongInt; virtual; abstract;
 public
 procedure X;
 end;
 
 // Здесь TMyObject.X видно, TMyObject.Y видно только наследникам TMyObject
 
 implementation
 
 // Всё также, ничего не поменялось
 
 type
 TMyObject = object
 procedure Z;
 protected
 // Эта процедура также составляет интерес: она, в отличии от метода Y,
 // не видна в коде, подключившим этот модуль, но видна в этом модуле ниже
 procedure W; virtual;
 end;
 
 // А тут уже видно ещё и Z
 
 procedure TMyObject.X;
 begin
 if Y > 0 then begin
 Z;
 end else
 W;
 end;
 
 procedure TMuObject.W;
 begin
 end;
 
 procedure TMyObject.Z;
 begin
 end;
 
 end.
 
Исключение составляют свойства. В свойствах можно использовать функции и процедуры, которые будут объявлены в секции реализации:
- Код: Выделить всё
- unit MyUnit;
 
 interface
 
 type
 TMyObject = forward object
 constructor Init;
 property X: LongInt read GetX write SetX;
 end;
 
 implementation
 
 const
 SomeConst = 5;
 
 type
 TMyObject = object
 FX: LontInt;
 function GetX: LongInt; inline;
 procedure SetX(const Value: LongInt);
 end;
 
 constructor TMyObject.Init;
 begin
 FX := SomeConst;
 end;
 
 function TMyObject.GetX: LongInt;
 begin
 Result := FX;
 end;
 
 procedure TMyObject.SetX(const Value: LongInt);
 begin
 FX := Value;
 end;
 
 end.
 
Кажется, что такую возможность должно быть несложно поддержать в компиляторе, т.к. описание свойства задаёт довольно сильные ограничения на сигнатуры геттеров и сеттеров.
Также концептуально некоторую проблему могут составить операторы, особенно операторы копирования, конструирования и выхода из области видимости (если таковые будут поддержаны в языке), т.к. объявленные только внутри implementation операторы и будут действовать только внутри implementation, и в силу их неявного действия объекты внутри юнита и за его пределами будут неявно вести себя по-разному. Чтобы не столкнуться с проблемами в связи с этим, рекомендуется не описывать операторы в implementation-части объектов.
Лекс Айрин писал(а):Дож писал(а):Как это нет? Пишется private и данные ограничены.
И вот так. И в С/с++ нет инкапсуляции. Есть модульный доступ к объектам.
При инкапсуляции вообще не должно быть левого доступа к полям объектов. Только через методы. Ну или через свойства, которые суть тоже методы.
 
И какие же из ныне используемых языков, по Вашему, являются ОО с инкапсуляцией?
Дож писал(а):Я хочу, чтобы мои программы шустро выполнялись, методы инлайнились, а не используемые методы библиотек не попадали в итоговый код.
То, что они туда попадают это неправильная работа оптимизатора. и она, на самом деле, не должна зависить от того виртуальный метод или нет.
Как правильно пишет 
Mikhail, это фундмаентальная проблема и она непросто решается.
1) Если в модуле A есть класс a, а в модуле B — его наследник b, и где-то в программе используется класс a, то компилятор не может просто так вырезать методы класса b, т.к. знание об их использовании — это некое Realtime-знание.
2) Вызовы виртуальных методов должны производиться через VMT, это медленнее, чем просто вызов функции, и ещё медленнее, чем inline короткой функции.
Дож писал(а):ООП — это не только виртуальные методы, но и удобный, логичный синтаксический сахара. У меня большинство написанных объектов не имеют виртуальных методов.
И вы, при этом, теряете возможность определять потомков с нужными свойствами -- ведь при этом наличие виртуальных методов обязательно.
Все методы, которые нужно переопределять, я делаю виртуальными. Большинство в этом не нуждаются. По коду сразу видно что нужно переопределять, а что для этого не предусмотрено.
Контраргумент, соразмерный аргументу: если все методы виртуальны, и в классе есть некий инвариант, то наследник может его легко нарушить, а нарушение инвариантов — это очень частый источник трудновылавливаемых ошибок.