Solved

delphi allows writing to private records. why?

Posted on 2003-11-20
7
339 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
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
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

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone 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

Suggested Solutions

Title # Comments Views Activity
Delphi 2 68
Delphi: ForceDirectory plain function 7 42
Firemonkey android show image from resource ? 1 46
how to make 2 step back? ..\..\ ExtractFilePath (paramstr(0)) 5 46
A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
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…
Email security requires an ever evolving service that stays up to date with counter-evolving threats. The Email Laundry perform Research and Development to ensure their email security service evolves faster than cyber criminals. We apply our Threat…
In a recent question (https://www.experts-exchange.com/questions/29004105/Run-AutoHotkey-script-directly-from-Notepad.html) here at Experts Exchange, a member asked how to run an AutoHotkey script (.AHK) directly from Notepad++ (aka NPP). This video…

790 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