Why can I have a local variable in a method that out-scopes a class property without a hint or warning?
Why can I have a local variable in a method that out-scopes a class property without a hint or warning?
One thing is allowing name overlaps for method parameters, but for local variables - does that even make sense?
type
TBadClass = class
private
FValue: Integer;
procedure SetValue(const Value: Integer);
public
procedure CheckValue;
property Value: Integer read FValue write SetValue;
end;
procedure TBadClass.SetValue(const Value: Integer);
begin
FValue := Value;
end;
procedure TBadClass.CheckValue;
var
Value: Integer;
begin
Value := 1;
Writeln('Value ', Value);
Writeln('Self ', Self.Value);
Self.Value := 2;
Writeln('Value ', Value);
Writeln('Self ', Self.Value);
end;
Output is
Value 1
Self 0
Value 1
Self 2
#XE6
One thing is allowing name overlaps for method parameters, but for local variables - does that even make sense?
type
TBadClass = class
private
FValue: Integer;
procedure SetValue(const Value: Integer);
public
procedure CheckValue;
property Value: Integer read FValue write SetValue;
end;
procedure TBadClass.SetValue(const Value: Integer);
begin
FValue := Value;
end;
procedure TBadClass.CheckValue;
var
Value: Integer;
begin
Value := 1;
Writeln('Value ', Value);
Writeln('Self ', Self.Value);
Self.Value := 2;
Writeln('Value ', Value);
Writeln('Self ', Self.Value);
end;
Output is
Value 1
Self 0
Value 1
Self 2
#XE6
I think this has been how the language behaves (and most other languages do). I know this is very odd, but technically you can access both, as your code shows. Same for a parameter matching a field.
ReplyDeleteWhat if you have some perfectly working code and you add a field? What if the field is added to a base class? Too many scenarios, I think, some of which could have merit...
This is how Delphi scope rules work. Inner block declarations always take precedence over outer block.
ReplyDeleteAdding warnings to that kind of behaviour would very likely result in having warnings all over your code.
I think that is one of the things that some metric tools like Pascal Analyzer can spot (not sure about the metrics that are included in higher versions of Delphi though)
ReplyDeleteP.S. FWIW thats an instance property and not a class property
A hint would make sense in many cases TBH.
ReplyDeleteYes, it would be annoying in the scenario described by Marco Cantù but on the other hand if you keep adding fields or methods with names overlapping local ones, you will eventually end up with a big ball of hard to maintain code.
You could use Pascal Analyzer by Peganza.com to find ambigious references or symbol overlapping.
ReplyDeleteEric Grange Yes, some hints the compiler could generate would be useful for sure. I think it goes into the same direction of the reintroduce keyword where you tell the compiler "YES, I know what I am doing and that I am hiding a virtual method!"
ReplyDeleteit reminds me of how grateful I am to Pascal not to impose the Self. prefix like $this-> in PHP :)
ReplyDeleteFor this reason i use a prefix for local variables (LValue), just like the F of FValue. Only properties dont have a prefix in my code.
ReplyDeleteI'd certainly like an option that would warn me of namespace pollution for local variables and withs, possibly also for unit scope clashes - with the option of turning it off per unit with a compiler directive.
ReplyDeletePosted a QC: http://qc.embarcadero.com/wc/qcmain.aspx?d=127171
ReplyDeleteA hint which can be disabled wouldn't hurt, but personally I'd much prefer making the language case sensitive. But apparently I'm weird like that :)
ReplyDeleteAsbjørn Heid I would like to have the language "case-exclusive" personally ie. you declare "Something" then you have to use "Something" everywhere, and can't declare "something" alongside, ie. no C/Java-like horror "Class class;"
ReplyDeleteEric Grange I've used C++ far too much not to enjoy that ;)
ReplyDelete