Lazarus

Programming => General => Topic started by: Imants on July 15, 2012, 01:54:13 pm

Title: Abstract classes
Post by: Imants on July 15, 2012, 01:54:13 pm
Is it ok that allows to create abstract classes? Like
 
  TAbstractClass = class abstract(TObject)
  public
    procedure Test; virtual; abstract;
  end;

var
  FTest: TAbstractClass;
begin
  FTest := TAbstractClass.Create; //shouldn't here need to bee an error
end.

but compiler compiles it and gives only a warning.
Title: Re: Abstract classes
Post by: Leledumbo on July 15, 2012, 02:45:15 pm
For me, it should indeed be an error. But maybe the developers have another thought, Delphi compatibility for instance (I don't know how it behaves it Delphi either).
Title: Re: Abstract classes
Post by: marcov on July 15, 2012, 04:10:27 pm
Yes that is ok. Sometimes classes contain abstract methods only for specific purposes (like streaming).

If you don't stream the relevant class you don't need to define them. If it was an error you would have to.   

Also it would create problems with versioning, e.g. when an abstract methods is added to a baseclass in a new FPC version, all old code wouldn't compile anymore till the new method was overriden.
Title: Re: Abstract classes
Post by: eny on July 15, 2012, 06:59:36 pm
Yes that is ok. Sometimes classes contain abstract methods only for specific purposes (like streaming).
There is a bit more to it.

From a pure OO perspective abstract classes should not (or better: can not!) be instantiated because it is unknown how the abstract methods are supposed to work. Hence the abstract classification. So it is a bad idea to instantiate abstract classes or allow them to be instantiated.
They serve an important purpose: to be at the top of an inheritance hierarchy.

Luckily the FPC compiler does recognizes them although they are only flagged as warnings (at least that's something).

If you want to have methods that 'do not have a purpose yet but they might', implement them as virtual and create an empty body.
(Although the programming paradigm YAGNI (http://en.wikipedia.org/wiki/You_ain%27t_gonna_need_it) also applies.)

Quote
Also it would create problems with versioning, e.g. when an abstract methods is added to a baseclass in a new FPC version, all old code wouldn't compile anymore till the new method was overriden.
True. Thats the reason why this shouldn't happen that often with classes already in usage. Especially in the LCL.
And if it does happen it is good the compiler recognizes it so the inheriting classes can be adapted.
(Or the the method not being defined as abstract but merely virtual as described above.)
Title: Re: Abstract classes
Post by: KpjComp on July 15, 2012, 07:14:14 pm
Delphi Allows it.
Title: Re: Abstract classes
Post by: Imants on July 15, 2012, 08:23:03 pm
Also it would create problems with versioning, e.g. when an abstract methods is added to a baseclass in a new FPC version, all old code wouldn't compile anymore till the new method was overriden.

I tried add abstract methods to base classes. And hoped that compiler would create errors in places where I create these classes like in java but it didn't then I masked all class abstract by writing "class abstract" it didn't do a thing either. So what is purpose of "abstract" token.

I understand that for old compatibility pascal allows to create classes with abstract methods but what use to allow to create class which is declared as abstract it self.
Title: Re: Abstract classes
Post by: eny on July 15, 2012, 08:26:29 pm
I understand that for old compatibility pascal allows to create classes with abstract methods but what use to allow to create class which is declared as abstract it self.
None.
Title: Re: Abstract classes
Post by: KpjComp on July 15, 2012, 09:58:14 pm
Quote
but what use to allow to create class which is declared as abstract it self.

I think because how can the compiler always know?.
eg.

Code: [Select]
type
  TSomething = class
     function SomeAbstractMethod:boolean; virtual; abstract;
  end;
  TSomethingClass = class of TSomething;

procedure CreateSomething(c:TSomethingClass);
var
  x:TSomething;
begin
  x := c.Create;  //how does the compiler know it's not got no overridden abstract methods?
end;

Also what if you wanted to  manipulate VMT's manually?, if you can't even create the class this option is out the window.

Also making empty Virtual methods, will of course make more redundant code, at least with virtual abstract all methods share the same code.  And in this case gives you a nice runtime error.
Title: Re: Abstract classes
Post by: totya on March 27, 2018, 10:23:02 pm
Yes, confirmed, abstract directive doesn't work, lazarus 1.6.4.
Title: Re: Abstract classes
Post by: Blaazen on March 27, 2018, 11:09:35 pm
@ Yes, confirmed, abstract directive doesn't work, lazarus 1.6.4.

What does it mean, "doesn't work"?

When I try to create abstract class with abstract method I got many warnings from compiler (one for each abstract method and one for the class itself (unit1.pas(36,38) Warning: Creating an instance of abstract class "TBaseScrollControl")). It is same for mode delphi and objfpc.
Even more, it depends on compiler, version of Lazarus is irrelevant.
From my point of view, it works well.
Title: Re: Abstract classes
Post by: jamie on March 27, 2018, 11:35:13 pm
Classes with Abstracts in them are great, cause you do not always need to implement all of them
and it is clearly documented in my old Delphi that it is the case and will generate a fault if you attempt to
execute a non implemented abstract..

 If guess if it bothers you, you could direct all unused abstracts to dummy methods..
Title: Re: Abstract classes
Post by: totya on March 27, 2018, 11:36:58 pm
What does it mean, "doesn't work"?

This is mean, I doesn't got compiler warnings or any, if a descendant class doesn't contain the abstract method.

I try to create sample later... Thanks.
Title: Re: Abstract classes
Post by: ASerge on March 28, 2018, 01:17:37 am
I think because how can the compiler always know?.
You have an unfortunate example. If an instance is created through a class reference, then it is correct that it does not know the exact class. But in the case of "TSomething.Create" there are no other options, and in theory, this should be a mistake. But for compatibility with Delphi it is left as is.
Title: Re: Abstract classes
Post by: jamie on March 28, 2018, 01:45:45 am
if memory serves I think all undefined abstracts point to a default Raise message, so in reality they do point to
something  :)
Title: Re: Abstract classes
Post by: Thaddy on March 28, 2018, 12:56:39 pm
in theory, this should be a mistake. But for compatibility with Delphi it is left as is.
Just curious? Which theory? Because that is not true. There is -more than a single - a necessity for it.
Suppose you would introduce an abstract method in a derived class? That should be legal and the class should be able to compile.
Object Pascal abstract classes should not be confused with C++ pure virtual. (You can use interfaces for that, though)

Since OP derived from a class that is NOT abstract it has to obey simple OOP principles and respect any virtual method that is not abstract.
Since TObject is not a virtual abstract class any derived classes are not fully "abstract" .
Title: Re: Abstract classes
Post by: totya on March 28, 2018, 06:25:24 pm
What does it mean, "doesn't work"?

Hi!

As I said, I create simple demo. I can't get any compiler warnings:

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Button1: TButton;
  16.     procedure Button1Click(Sender: TObject);
  17.   end;
  18.  
  19. var
  20.   Form1: TForm1;
  21.  
  22. implementation
  23.  
  24. {$R *.lfm}
  25.  
  26. uses
  27.   Unit3;
  28.  
  29. { TForm1 }
  30.  
  31. procedure TForm1.Button1Click(Sender: TObject);
  32. begin
  33.   DataModule1.MyShow;
  34. end;
  35.  
  36. end.
  37.  

Code: Pascal  [Select][+][-]
  1. unit Unit2;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil,
  9.  
  10.   Dialogs;
  11.  
  12. type
  13.   TCustomDataModule = class(TDataModule)
  14.   protected
  15.     procedure ImportantAbstractProcedureNeedToOverrideButNothingHappen; dynamic; abstract;
  16.   public
  17.     procedure MyShow;
  18.   end;
  19.  
  20. var
  21.   CustomDataModule: TCustomDataModule;
  22.  
  23. implementation
  24.  
  25. {$R *.lfm}
  26.  
  27. procedure TCustomDataModule.MyShow;
  28. begin
  29.   ShowMessage('OK');
  30. end;
  31.  
  32. end.
  33.  

Code: Pascal  [Select][+][-]
  1. unit Unit3;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Sqlite3DS, db, FileUtil,
  9.  
  10.   Unit2;
  11.  
  12. type
  13.  
  14.   { TDataModule1 }
  15.  
  16.   TDataModule1 = class(TCustomDataModule)
  17.     DataSource1: TDataSource;
  18.     Sqlite3Dataset1: TSqlite3Dataset;
  19.   end;
  20.  
  21. var
  22.   DataModule1: TCustomDataModule;
  23.  
  24. implementation
  25.  
  26. {$R *.lfm}
  27.  
  28. end.
  29.  
Title: Re: Abstract classes
Post by: Blaazen on March 28, 2018, 08:16:37 pm
@ As I said, I create simple demo. I can't get any compiler warnings:

Where do you create DataModule1?!
No creating, no warning.  :)

EDIT:

This gives warnings:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. begin
  3.   DataModule1:=TDataModule1.Create(self);
  4.   DataModule1.MyShow;
  5.   DataModule1.Free;
  6. end;  
Title: Re: Abstract classes
Post by: totya on March 28, 2018, 08:22:36 pm
Where do you create DataModule1?!
No creating, no warning.  :)

OMG... Button1.Click is working, because Datamodule1 is created (with autocreate), see attached file my previous post, or see this:

Code: Pascal  [Select][+][-]
  1. program project1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses
  6.   {$IFDEF UNIX}{$IFDEF UseCThreads}
  7.   cthreads,
  8.   {$ENDIF}{$ENDIF}
  9.   Interfaces, // this includes the LCL widgetset
  10.   Forms, sqlite3laz, Unit1, Unit2, Unit3
  11.   { you can add units after this };
  12.  
  13. {$R *.res}
  14.  
  15. begin
  16.   RequireDerivedFormResource:=True;
  17.   Application.Initialize;
  18.   Application.CreateForm(TDataModule1, DataModule1);
  19.   Application.CreateForm(TForm1, Form1);
  20.   Application.Run;
  21. end.
  22.  
Title: Re: Abstract classes
Post by: Blaazen on March 28, 2018, 08:43:37 pm
Ah, I see now. Coincidently, it didn't crash when DataModule1 wasn't autocreated.

So yes, in this case there are no warnings. Probably because CreateForm creates instance in unusual way.
Title: Re: Abstract classes
Post by: totya on March 28, 2018, 09:13:59 pm
This gives warnings:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. begin
  3.   DataModule1:=TDataModule1.Create(self);
  4.   DataModule1.MyShow;
  5.   DataModule1.Free;
  6. end;  

Yes, me too. TDatamodule isn't a really form... even hidden... Thanks for the tip!
Title: Re: Abstract classes
Post by: PascalDragon on April 06, 2018, 04:18:37 pm
For those that want the compiler to stop when creating an abstract class or a class with abstract methods: use the following in an include file or so.  8)
Code: Pascal  [Select][+][-]
  1. {$warn 4122 error} // creating an abstract class
  2. {$warn 4046 error} // creating a class with an abstract method
Title: Re: Abstract classes
Post by: Thaddy on April 06, 2018, 04:23:26 pm
 :D
 8)
TinyPortal © 2005-2018