I'm trying to check if my private procedures are really private. But it works the way it shouldn't.
Please help me, maybe I missed something about how the incapsulation should work.
This code should not work. I guess. But it works.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
tmyclass = class
private
procedure one;
end;
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
public
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure tmyclass.one;
begin
ShowMessage('1');
end;
procedure TForm1.Button1Click(Sender: TObject);
var myclass:tmyclass;
begin
myclass.one;
end;
end.
Thank you. (Delphi-7, Win7 x64).
private
is for a unit
.
With more recent version of Delphi, you can use strict private
to get the expected behavior.
The meaning of private
is clearly documented:
Private, Protected, and Public Members
A private member is invisible outside of the unit or program where its
class is declared. In other words, a private method cannot be called
from another module, and a private field or property cannot be read or
written to from another module. By placing related class declarations
in the same module, you can give the classes access to one another's
private members without making those members more widely accessible.
For a member to be visible only inside its class, it needs to be
declared strict private.
A protected member is visible anywhere in the module where its class
is declared and from any descendent class, regardless of the module
where the descendent class appears. A protected method can be called,
and a protected field or property read or written to, from the
definition of any method belonging to a class that descends from the
one where the protected member is declared. Members that are intended
for use only in the implementation of derived classes are usually
protected.
A public member is visible wherever its class can be referenced.
Strict Visibility Specifiers
In addition to private and protected visibility specifiers, the Delphi
compiler supports additional visibility settings with greater access
constraints. These settings are strict private and strict protected
visibility. These settings can be used in Win32 applications.
Class members with strict private visibility are accessible only
within the class in which they are declared. They are not visible to
procedures or functions declared within the same unit. Class members
with strict protected visibility are visible within the class in which
they are declared, and within any descendent class, regardless of
where it is declared. Furthermore, when instance members (those
declared without the class or class var keywords) are declared strict
private or strict protected, they are inaccessible outside of the
instance of a class in which they appear. An instance of a class
cannot access strict protected or strict protected instance members in
other instances of the same class.
Delphi's traditional private visibility specifier maps to the CLR's
assembly visibility. Delphi's protected visibility specifier maps to
the CLR's assembly or family visibility.
Note: The word strict is treated as a directive within the context of a class declaration. Within a class declaration you cannot declare
a member named 'strict', but it is acceptable for use outside of a
class declaration.
Your version of Delphi, Delphi 7, does not support the strict
specifiers.
Here are two sample units to show the visibility of private
, protected
and public
parts from a class.
unit BaseClass;
interface
type
TBaseClass0 = class
strict private
FStrictPrivate : Integer;
private
FPrivate : Integer;
strict protected
FStrictProtected : Integer;
protected
FProtected : Integer;
public
FPublic : Integer;
procedure DoSomeThing; virtual;
end;
TBaseClass1 = class( TBaseClass0 )
public
procedure DoSomeThing; override;
end;
procedure DoSomeThing( ABase : TBaseClass0 );
implementation
{ TBaseClass0 }
procedure TBaseClass0.DoSomeThing;
begin
FStrictPrivate := 0;
FPrivate := 0;
FStrictProtected := 0;
FProtected := 0;
FPublic := 0;
end;
{ TBaseClass1 }
procedure TBaseClass1.DoSomeThing;
begin
inherited;
// FStrictPrivate := 1; // no access
FPrivate := 1;
FStrictProtected := 1;
FProtected := 1;
FPublic := 1;
end;
procedure DoSomeThing( ABase : TBaseClass0 );
begin
with ABase do
begin
// FStrictPrivate := 3; // no access
FPrivate := 3;
// FStrictProtected := 3; // no access
FProtected := 3;
FPublic := 3;
end;
end;
end.
unit BaseClass2;
interface
uses
BaseClass;
type
TBaseClass2 = class( TBaseClass0 )
public
procedure DoSomeThing; override;
end;
procedure DoSomeThing( ABase : TBaseClass0 );
implementation
{ TBaseClass2 }
procedure TBaseClass2.DoSomeThing;
begin
inherited;
// FStrictPrivate := 2; // no access
// FPrivate := 2; // no access
FStrictProtected := 2;
FProtected := 2;
FPublic := 2;
end;
procedure DoSomeThing( ABase : TBaseClass0 );
begin
with ABase do
begin
// FStrictPrivate := 4; // no access
// FPrivate := 4; // no access
// FStrictProtected := 4; // no access
// FProtected := 4; // no access
FPublic := 4;
end;
end;
end.