delphi allows writing to private records. why?

type
  TID3v1 = record
    Artist            : string[30];
    ... {some more variables}
  end;
  TMP3Info = class
    private
      pID3v1          : TID3v1;
    public
      property ID3v1  : TID3v1 read pID3v1;
  end;
...
var
  mp3 : TMP3Info;
begin
mp3 := TMP3Info.Create;
...

mp3.ID3v1.Artist := 'some value';
  there is no problem, delphi says what it should say: [Error] Unit1.pas(36): Left side cannot be assigned to

with mp3.ID3v1 do Artist := 'some value';
  writes value to variable. why?!? shouldn't it say that 'left side cannot be assigned to' ? how to do so that delphi doesn't allow writing to variable this way ?
LVL 11
ZhaawZSoftware DeveloperAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

jcondeCommented:
listening ...

I have noticed the same and was about to ask this question !  ... If I was to guess, the reason for this is delphi treats all classes in the same file as "friends", but that's only a guess and I haven't tested this out yet.
0
scrapdogCommented:
My guess is that it has nothing to do with accessibility...the "with" statement is probably obtaining a pointer to the record, and a record's members are always public...visibility rules are probably not enforced in the with statement.

Maybe if you create a "get" method for your property, it will accomplish what you want.  Users of your class may still be able to assign to it in the "with" statement, but it would be guaranteed that they would be writing to a copy of the record rather than the original (though it would be inefficient).

I try to avoid using records a properties in general.  Perhaps making your structure a class might be a safer idea.
0
robert_marquardtCommented:
This is not a problem of private since you access the public ID3v1.
The error is correctly raised for ID3v1 not having a write part.
The other statement seems to work because with creates an anonymous variable pointing to the implementation of ID3v1 aka pID3v1.
0
Cloud Class® Course: Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

kretzschmarCommented:
hmm,

i would say

>mp3.ID3v1.Artist := 'some value';
> there is no problem, delphi says what it should say: [Error]
>Unit1.pas(36): Left side cannot be assigned to

i would say, this is a bug, because it should possible to
change one attribute of the record

-------
property ID3v1  : TID3v1 read pID3v1;
 
this says only, that the record pID3v1 as whole cannot replaced,
like
 ID3v1 := OtherID3v1;

-------

the with operates like

procedure TForm1.Button1Click(Sender: TObject);
var
  mp3 : TMP3Info;
  ID3v1Ref : ^TID3v1;
begin
  mp3 := TMP3Info.Create;
  ID3v1Ref := addr(mp3.ID3v1);
  ID3v1Ref.Artist := 'Whatever';
  ShowMessage(mp3.ID3v1.Artist);

  ...

end;

the correct bahaviour you have, if you change your record to
an object,

my testSample:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TID3v1 = record
    Artist            : string[30];
  end;

  TID3v1Obj = Class
  Private
    FArtist            : string;
    FArtistReadOnly    : string;
  published
    property Artist : String read FArtist write FArtist;
    property ArtistReadOnly : String read FArtistReadOnly;
  end;

  TMP3Info = class
    private
      pID3v1          : TID3v1;
      pID3v1Obj       : TID3v1Obj;
    public
      constructor Create;
      destructor Destroy;
    published
      property ID3v1  : TID3v1 read pID3v1;
      property ID3v1Obj : TID3v1Obj read pID3v1Obj;
  end;


var
  Form1: TForm1;

implementation

{$R *.dfm}

constructor TMP3Info.Create;
begin
  inherited;
  pID3v1Obj := TID3v1Obj.Create;
  //as it is in the same unit, i can access it directly
  pID3v1Obj.FArtistReadOnly := 'ReadOnly';
end;

destructor TMP3Info.Destroy;
begin
  pID3v1Obj.Free;
  Inherited;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  mp3 : TMP3Info;
  ID3v1Ref : ^TID3v1;
begin
  //how with works
  mp3 := TMP3Info.Create;
  ID3v1Ref := addr(mp3.ID3v1);
  ID3v1Ref.Artist := 'Whatever';
  ShowMessage(mp3.ID3v1.Artist);

  //with Objects, instead of records
  mp3.ID3v1Obj.Artist := 'Whatever'; //No Problem

  //this didn't compile
  //mp3.ID3v1Obj.ArtistReadOnly := 'Whatever';

  //also this didn't compile
  //with mp3.ID3v1Obj do ArtistReadOnly := 'Whatever';

  ShowMessage(mp3.ID3v1Obj.Artist);

  ShowMessage(mp3.ID3v1Obj.ArtistReadOnly);

  mp3.Free;
end;

end.

meikl ;-)

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
robert_marquardtCommented:
meikl is right as always ;-)
0
ZhaawZSoftware DeveloperAuthor Commented:
tx for the answers ;)
another question -

TClass = class
  private
    FValue : string;
  published
    property Value : string read FValue write FValue;
    OtherValue : string;
  end;

is there any difference between Value and OtherValue ?
0
andrewjbCommented:
... you'r also right that all classes within the same unit are effectively treated as friends to each other, and private/protected/public don't apply


Q2) Not really. I can't think of anything that you could do where the first works and the second doesn't, or vice-versa...
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.