4

I am new of Delphi. In the documentation of TStrem class, i read it is an abstract class. So i think the compiler goes in error when i try to create it with

stream := TStream.Create();

Why not?

user3083618
  • 270
  • 1
  • 4
  • 16

1 Answers1

7

The Delphi language doesn't really have any formal concept of abstract class.

It is true that you can define a class to be abstract:

type
  TMyClass = class abstract
  end;

But you can perfectly well instantiate this class. In fact class abstract in Delphi is a feature used only by the long abandoned Delphi .net compiler.

A more useful definition of an abstract class is one that contains abstract methods. If you attempt to instantiate such a class, then a compiler warning will be emitted. Those warnings can be promoted to errors by way of a compiler option, if you wish.

When the documentation refers to TStream as being abstract it in fact means that it is "conceptually" abstract. In fact it does not even have any abstract methods, so by my definition above it is not abstract.

I'm really not sure why TStream does not contain abstract methods. I would suggest that the GetSize, SetSize, Read, Write and Seek should really be declared abstract. I suspect that if the class were being designed today then they would be declared abstract and likely they are not for historical reasons.

Instantiating TStream is a very common mistake made by programmers less experienced in the Delphi RTL. Once the mistake has been made a couple of times, the lesson is usually learnt. Unfortunately the system provides no easy way for this mistake to be flagged up. Each and every new programmer just has to learn the hard way.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • I think that they wont change some methods to abstract because there could be issues with some (maybe big and/or old) projects that actually use them – Alberto Miola Jun 22 '17 at 15:54
  • @AlbertoMiola *I suspect that if the class were being designed today then they would be declared `abstract` and likely they are not for historical reasons.* – David Heffernan Jun 22 '17 at 15:58
  • @DavidHeffernan If TStream is abstractly conceptually, the instance is conceptual error too. If I forget it and use TStream and its methods directly (ie not the TMemoryStream methods), the code works well. Or not? – user3083618 Jun 23 '17 at 09:09
  • No, if you instantiate a `TStream`, then none of its methods do anything useful. – David Heffernan Jun 23 '17 at 09:20
  • `Read` and `Write` were abstract at least as late as Delphi 2005. However, `Seek` was not abstract anymore because `TStream` was extended to support 64-bit offsets, which the original `Seek` couldn't do. The base class uses some tricks to figure out which `Seek` was overridden, and then makes the other method call the overridden one. I assume something similar was done for `Read` and `Write` at some point, so that descendant classes wouldn't necessarily have to implement _all_ the virtual methods, just whichever ones were most convenient. – Rob Kennedy Jun 27 '17 at 19:03
  • @DavidHeffernan "none of its methods do anything useful" What do you mean? I use a CreateBlobStream, a function of the TFDQuery class. It returns a TStream type. My code is: function getSizeOfStream(TFDQuery q):int64; var stream:TStream; begin stream:=TStream.Create; stream:= q.createBlobStream('blob_field'); result:=stream.size; end; The compiler compiles and the code returns the size of stream. – user3083618 Jun 28 '17 at 10:56
  • I mean the virtual methods implemented in `TStream`. Descendent classes, such as that returned by `CreateBlobStream` override those virtuals to do real work. – David Heffernan Jun 28 '17 at 11:09
  • Can i know the type of the discendent class of TStream returned by CreateBlobStream? Thanks a lot @DavidHeffernan – user3083618 Jun 28 '17 at 11:17
  • 1
    You don't need to know that. It's quite possibly a private type, defined in the implementation section of a unit and so not available to you. You can query `ClassType` on any instance to obtain the runtime type. But I repeat, you don't need to know this. The entire point of the `CreateBlobStream` abstraction is that the runtime type is not something you should be caring about. – David Heffernan Jun 28 '17 at 11:19