Это будет работать в Delphi. Код в том же модуле, что и используемые им классы, имеет неявный доступ к защищенным (но не строго защищенным) членам, даже тем членам, которые объявлены в другом модуле. Вы объявляете собственность защищенной в CustomLabel
:
type
CustomLabel = class
private
FBold: Boolean;
protected
property Bold: Boolean read FBold write FBold;
end;
Процедура установки жирным шрифтом в другом блоке будет иметь собственный потомок CustomLabel
:
type
TAccessCustomLabel = class(CustomLabel);
procedure SetBold(customLabel: CustomLabel)
begin
TAccessCustomLabel(customLabel).Bold := True;
end;
Вы не можете использовать as
приведение, потому что фактический параметр никогда не будет экземпляром TAccessLabel
. Это будет экземпляр AngleLabel
или NormalLabel
, но поскольку части, унаследованные от CustomLabel
всеми тремя классами, являются общими, свойство Bold
одинаково во всех них. Это остается верным даже после того, как свойство было опубликовано или опубликовано в потомке:
type
AngleLabel = class(CustomLabel)
public
property Bold;
end;
Вы можете изменить видимость свойств, но не полей. Если вы попробуете то же самое с полем, вы объявите новое поле с тем же именем, которое скрывает унаследованное поле.
Вы можете сделать что-то подобное в C ++, но это не так часто, как в Delphi, так что, скорее всего, это вызовет ярость, особенно если вы собираетесь писать переносимый код.
Объявите четвертый класс, как в Delphi. C ++ не так свободен в доступе к членам, как Delphi, но в нем есть концепция дружба , которая в этом случае работает так же хорошо.
class AccessCustomLabel: public CustomLabel
{
friend void SetLabel(CustomLabel* customLabel);
};
Эта функция теперь имеет полный доступ к членам класса:
void SetLabel(CustomLabel* customLabel)
{
// Not allowed:
// customLabel->bold = true
// Not ordinarily allowed; requires friendship
reinterpret_cast<AccessCustomLabel*>(customLabel)->bold = true;
}
Технически это неопределенное поведение , потому что мы привели тип объекта к типу, которого он на самом деле не имеет. Мы полагаемся на то, что все потомки CustomLabel
имеют одинаковую разметку, в частности, чтобы bold
член AccessCustomLabel
находился в той же относительной позиции, что и bold
член любого другого CustomLabel
потомка .
Приведение типов в коде Delphi и C ++ выполняет type punning . Это не сойдет с рук в C # или Java; они проверяют результаты своих приведений, поэтому, если customLabel
на самом деле не содержит экземпляр AccessCustomLabel
, вы получите исключение. Вы должны будете использовать отражение, чтобы получить доступ к защищенным членам не связанных классов на этих языках. Демонстрируя это за пределами моей глубины.