Scopes and names can really be deceiving. A root class and a descendant class can both have public fields, properties and methods with the same name.
Scopes and names can really be deceiving. A root class and a descendant class can both have public fields, properties and methods with the same name.
I really wonder why this doesn't raise a warning or a even a hint?
(Berlin 10.1.x / Tokyo 10.2.x)
Output:
c: 1
TClass1:1
TClass1.PropTest:1
TClass2.Test:2
TClass2.PropTest:2
TClass1.Oops
Press any key:
Code:
program PublicScope;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
type
TClass1 = class
public
Test: Integer;
constructor Create; virtual;
procedure Dump; virtual;
procedure Oops;
property PropTest:Integer read Test;
end;
TClass2 = class(TClass1)
public
Test:Integer;
constructor Create; override;
procedure Dump; override;
procedure Oops;
property PropTest:Integer read Test;
end;
{ TClass1 }
constructor TClass1.Create;
begin
Test := 1;
end;
procedure TClass1.Dump;
begin
Writeln('TClass1:', Test);
Writeln('TClass1.PropTest:', Test);
end;
procedure TClass1.Oops;
begin
Writeln('TClass1.Oops');
end;
{ TClass2 }
constructor TClass2.Create;
begin
Inherited;
Test := 2;
end;
procedure TClass2.Dump;
begin
Inherited;
Writeln('TClass2.Test:', Test);
Writeln('TClass2.PropTest:', Test);
end;
procedure TClass2.Oops;
begin
Writeln('TClass2.Oops');
end;
procedure Test;
var
c: TClass1;
begin
c := TClass2.Create;
try
Writeln('c: ', c.Test);
c.Dump;
c.Oops;
finally
c.Free;
end;
end;
begin
try
try
Test;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
finally
Write('Press any key: ');
Readln;
end;
end.
I really wonder why this doesn't raise a warning or a even a hint?
(Berlin 10.1.x / Tokyo 10.2.x)
Output:
c: 1
TClass1:1
TClass1.PropTest:1
TClass2.Test:2
TClass2.PropTest:2
TClass1.Oops
Press any key:
Code:
program PublicScope;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
type
TClass1 = class
public
Test: Integer;
constructor Create; virtual;
procedure Dump; virtual;
procedure Oops;
property PropTest:Integer read Test;
end;
TClass2 = class(TClass1)
public
Test:Integer;
constructor Create; override;
procedure Dump; override;
procedure Oops;
property PropTest:Integer read Test;
end;
{ TClass1 }
constructor TClass1.Create;
begin
Test := 1;
end;
procedure TClass1.Dump;
begin
Writeln('TClass1:', Test);
Writeln('TClass1.PropTest:', Test);
end;
procedure TClass1.Oops;
begin
Writeln('TClass1.Oops');
end;
{ TClass2 }
constructor TClass2.Create;
begin
Inherited;
Test := 2;
end;
procedure TClass2.Dump;
begin
Inherited;
Writeln('TClass2.Test:', Test);
Writeln('TClass2.PropTest:', Test);
end;
procedure TClass2.Oops;
begin
Writeln('TClass2.Oops');
end;
procedure Test;
var
c: TClass1;
begin
c := TClass2.Create;
try
Writeln('c: ', c.Test);
c.Dump;
c.Oops;
finally
c.Free;
end;
end;
begin
try
try
Test;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
finally
Write('Press any key: ');
Readln;
end;
end.
Because it was never implemented and the designers of the language never paid attention to its consistency. C# for example raises a warning telling you that a member is hiding an inherited member and you need to explicitly add the new keyword (similar to reintroduce for virtual methods in Delphi).
ReplyDeleteWell, I'd want at least a hint, and perhaps a compiler switch to ignore such hints, for those that abuse the way it works today.
ReplyDeleteI guess I should QP it.
This is where static code analysis comes to the rescue. At least Pascal Expert and Pascal Analyzer (http://peganza.com/) do emit these hints (not sure about FixInsight here).
ReplyDeleteEach time I hear claims that the IDE should do it in the first place, I am glad that it does not and thus opens a market for those kinds of external tools. If this market vanishes we will probably loose some really helpful tools and tool developers.
Even worse in my view is the hiding that occurs when using units.
ReplyDeleteDavid Heffernan - I agree. Yes, it can come in handy - but overall, I find it to be a risk.
ReplyDeleteUwe Raabe The C# compiler does and there is still a market for VS extensions (see Resharper). So whats your point? That making a product that lacks basic features is good for third party eco system?
ReplyDeleteStefan Glienke Not literally, but sort of, yes - when removing the "basic". The market for VS extensions may still be big enough to make some profit even if it is comparable small. That doesn't hold true for Delphi. Note that I don't want to bind this to the explicit issue shown above. It is more of a general statement. So I would not phrase it "lack of basic features", but rather "containing the basics, but giving room for nice and useful things to 3rd parties". Preferences may differ here and not everything useful for myself gets the same appreciation by others. Putting all things into the main product may reduce diversity in the end.
ReplyDeleteThe problem is that the standard answer to "IDE lacks feature xy" (and most of the time that's not something fancy) is: "with (most of the time a commercial one) you can do that"
ReplyDeleteAnd especially seasoned developers are very much subject to habit and "been doing it like that since..." that they don't see how much better it could be.
Also FWIW StyleCop runs circles around any static code analysis tool available for Delphi and is open source.
Uwe Raabe but wouldn't that mean a good plugin mechanism?
ReplyDeleteNicholas Ring Indeed! Don't get me wrong: I still see much room for improvement for the IDE. It is definitely far from perfect.
ReplyDeleteLars Fosdal In what way is this ever handy?
ReplyDeleteDavid Heffernan - You can "inject" a replacement class or method, simply by adding the scope overshadowing unit in the uses clause. Handy for avoiding replacing a multitude of class type declarations or method references. I've typically used it for debugging scenarios.
ReplyDeleteOne example is using it for intercepting OutputDebugString to capture output to a log file system without having to replace a multitude of references.
Lars Fosdal OK, but there are plenty of other ways to do that. And the other ways are generally more explicit. I certainly don't think it's worth all the downsides.
ReplyDeleteDavid Heffernan I agree.
ReplyDelete