Solved

delphi allows writing to private records. why?

Posted on 2003-11-20
7
338 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
ID: 9792026
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
ID: 9794711
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
ID: 9794982
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
Problems using Powershell and Active Directory?

Managing Active Directory does not always have to be complicated.  If you are spending more time trying instead of doing, then it's time to look at something else. For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why

 
LVL 27

Accepted Solution

by:
kretzschmar earned 50 total points
ID: 9795153
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
ID: 9795363
meikl is right as always ;-)
0
 
LVL 11

Author Comment

by:ZhaawZ
ID: 9795458
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
ID: 9796181
... 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

ScreenConnect 6.0 Free Trial

Explore all the enhancements in one game-changing release, ScreenConnect 6.0, based on partner feedback. New features include a redesigned UI, app configurations and chat acknowledgement to improve customer engagement!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Two types of users will appreciate AOMEI Backupper Pro: 1 - Those with PCIe drives (and haven't found cloning software that works on them). 2 - Those who want a fast clone of their boot drive (no re-boots needed) and it can clone your drive wh…
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…

832 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