?
Solved

delphi allows writing to private records. why?

Posted on 2003-11-20
7
Medium Priority
?
351 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 27

Accepted Solution

by:
kretzschmar earned 150 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

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Michael from AdRem Software outlines event notifications and Automatic Corrective Actions in network monitoring. Automatic Corrective Actions are scripts, which can automatically run upon discovery of a certain undesirable condition in your network.…
In this video you will find out how to export Office 365 mailboxes using the built in eDiscovery tool. Bear in mind that although this method might be useful in some cases, using PST files as Office 365 backup is troublesome in a long run (more on t…

765 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