Solved

delphi allows writing to private records. why?

Posted on 2003-11-20
7
329 Views
Last Modified: 2010-04-05
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 ?
0
Comment
Question by:ZhaawZ
7 Comments
 
LVL 7

Expert Comment

by:jconde
Comment Utility
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
 
LVL 5

Expert Comment

by:scrapdog
Comment Utility
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
 
LVL 11

Expert Comment

by:robert_marquardt
Comment Utility
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
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
LVL 27

Accepted Solution

by:
kretzschmar earned 50 total points
Comment Utility
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
 
LVL 11

Expert Comment

by:robert_marquardt
Comment Utility
meikl is right as always ;-)
0
 
LVL 11

Author Comment

by:ZhaawZ
Comment Utility
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
 
LVL 12

Expert Comment

by:andrewjb
Comment Utility
... 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

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now