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?
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.
Related
The following declaration:
type
TRec = record
constructor Create;
end;
produces this compilation error:
E2394 Parameterless constructors not allowed on record types
The documentation rather unhelpfully states:
No further information is available for this error or warning.
My question is why the language was designed this way. Was it done this way purely to echo the analogous restriction for C# structs?
The language guide says this:
Records are constructed automatically, using a default no-argument constructor, but classes must be explicitly constructed. Because records have a default no-argument constructor, any user-defined record constructor must have one or more parameters.
But that doesn't make much sense. If there is a default constructor for a record, it can't be found through RTTI. And even if there was, why would that imply that it was impossible to add another one? You can do so for classes.
Perhaps the rationale is that if we were allowed to define our own parameterless constructors, we'd expect the compiler to call them automatically.
Note: I understand that you can use a parameterless static class function as a workaround. Indeed, I personally always prefer to use static class function instead of record constructors. But that's not the point of the question. What I really want to know is why parameterless constructors are not allowed on record types.
I can't give you a definitive answer (only the compiler builders can), but I suspect it is not related to Delphi's .NET past, but rather to Delphi's relation with C++Builder.
As cppreference says:
A default constructor is a constructor which can be called with no arguments (either defined with an empty parameter list, or with default arguments provided for every parameter).
C++ allows for parameterless constructors, and these parameterless constructors would become the default constructor, in C++. A default constructor is called in many situations, e.g. if you simply declare:
Foo myFoo;
The default constructor is called. This does not happen in Delphi, but a C++ programmer might expect it. Similarly, if you do:
Foo elements[1000];
The default constructor is called on each element (I checked that). This also doesn't happen in Delphi, although a C++ programmer might expect it.
Other hints that this is C++-related:
Constructors with different names (e.g. Init) are not allowed either. This seems to point to conflicts with C++ or with C#, as in both, constructors have the name of the class or struct, so any parameterless constructor would be mapped to Foo() (in a struct or class called Foo.)
Constructors with only default parameters are not allowed either. This matches the cppreference description for default constructors with only default arguments.
All in all, there are hints that parameterless constructors (or ones with only default parameters) conflict with C++ (i.e. C++Builder) and that that is why they are not allowed.
Note that this is not the only restriction caused by differences with C++: e.g. in Delphi you can't cast integers to and from floating point types either, because in C and C++, that would cause a conversion, while in Delphi, it would merely cause a reinterpretation of the bits. In order not to confuse people who were coming to Delphi from C or C++, the casting restriction was placed on floating point types. There may be more.
I downloaded the OTL http://www.omnithreadlibrary.com/
and compile the D2007 grouproj, install the package, without problem.
I then create a simple console application that uses OtlParallel unit, of course, I add the OtlParallel and some other pas files to the project.
But it complains that Generics.Collections is not found.
The documentation says:
High-level abstractions are implemented in the OtlParallel unit. They are all created through the factory class Parallel. High-level code intensively uses anonymous methods and generics which makes Delphi 2009 the minimum supported version.
This us of both generics and anonymous methods makes this unit completely incompatible with Delphi 2007.
If you wish to use a construct like Parallel.For with Delphi 2007 and OTL then you will have to back-port OtlParallel yourself. Without anonymous methods this is very difficult to do and achieve the same fluid style of code. You would have to use procedural types instead of anonymous methods. And you would have to implement closures manually.
So instead of using
TProc = reference to procedure;
you would use
TMethod = procedure of object;
And then to implement this you create a class or record with a parameterless method. You'll need to add whatever state is needed as members of the type, and populate those members. That is in essence a manual implementation of a closure with variable capture. And you'll need to deal with lifetime. Make sure that the instances outlive the parallel loop.
Good luck!
I'm attempting to write a unit test for a simple factory class that creates one of several possible implementing objects and returns it as an interface reference.
DUnit has a built in procedure, CheckIs(AObject: TObject; AClass: TClass; msg: string), that based on its name and the parameters it accepts should fail the test if the object's class type doesn't match the expected one. The only problem is it requires an object reference not an interface reference.
So I'm trying to use CheckTrue and perform the comparison in the body of the test but I'm not as familiar with Delphi's type checking support as I am with C#'s.
I know the is operator is out of the question since it only works with object references.
CheckTrue(LMyInterfaceReference {comparison here} TMyClass);
Any suggestions?
BTW, I'm using Delphi 2009 so I don't have access to the new RTTI support added in 2010+.
I'm wondering why you MUST have to test this... maybe you really don't have to.
But if knowing the underlying object of a Interface is a must, you have two choices:
Add a method to the interface which returns the underlying object, just a TObject, and implement this in each class just by returning self.
Hack a bit, for example using this Interface to object routine.
If you don't like hacks and don't feel like upgrading to Delphi 2010+ you may use an interface like this:
IImplementingObjectInterface = interface
function GetImplementingObject: TObject;
end;
Make sure your objects also implement this interface and use it to extract the implementing object. If you need to do this for a lot of objects you can define your own TInterfacedObject derivate that already implements this so you can simply change your inheritance and be done.
Barry Kelly (one of the main Embarcadero Delphi Compiler Engineers) wrote a nice An ugly alternative to interface to object casting this week.
It answers your question.
The fun is that Hallvard Vassbotn wrote a very similar piece of code back in 2004.
From Delphi 2010 on, you can just use an is check or as cast to go back from interface references to object references.
--jeroen
I have used Delphi classes for a while now but never really got into using interfaces. I already have read a bit about them but want to learn more.
I would like to hear which pros and cons you have encountered when using interfaces in Delphi regarding coding, performance, maintainability, code clearness, layer separation and generally speaking any regard you can think of.
All I can think of for now:
Pros:
Clear separation between interface and implementation
Reduced unit dependencies
Multiple inheritance
Reference counting (if desired, can be disabled)
Cons:
Class and interface references cannot be mixed (at least with reference counting)
Getter and setter functions required for all properties
Reference counting does not work with circular references
Debugging difficulties (thanks to gabr and Warren for pointing that out)
Adding to the answers few more advantages:
Use interfaces to represent the behavior and each implementation of a behavior will implement the interface.
API Publishing: Interfaces are great to use when publishing APIs. You can publishing an interface without giving out the actual implementation. So you are free to make internal structural changes without causing any problems to the clients.
All I say is that interfaces WITHOUT reference counting are VERY HIGH on my wishlist for delphi!!!
--> The real use of interfaces is the declaration of an interface. Not the ability for reference counting!
There are some SUBTLE downsides to interfaces that I don't know if people consider when using them:
Debugging becomes more difficult. I have seen a lot of strange difficulties stepping into interfaced method calls, in the debugger.
Interfaces in Delphi come with IUnknown semantics, if you like it or not, you'r stuck with reference counting being a supported interface. And, thus, with any interfaces created in Delphi's world, you have to be sure you handle reference counting correctly, and if you don't, you'll end up with leaks. When you want to avoid reference counting, your only choice is to override addref/decref and don't actually free anything, but this is not without its own problems. I find that the more heavily interface-laden codebases have some of the hardest-to-find access violations, and memory leaks, and this is, I think because it is very difficult to combine the refcount semantics, and the default delphi semantics (owner frees objects, and nobody else does, and most objects live for the entire life of their parents.).
Badly-done implementations using Interfaces can contribute some nasty code-smells. For example, Interfaces defined in the same unit that defines the initial concrete implementation of a class, add all the weight of interfaces, without really providing proper separation between the users of the interfaces and the implementors. I know this isn't a problem with interfaces themselves, but more of a quibble with those who write interface-based code. Please put your interface declarations in units that only have those interface declarations in them, and avoid unit-to-unit dependency hell caused by glomming your interface declarations into the same units as your implementor classes.
I mostly use interfaces when I want objects with different ancestry to offer a common service. The best example I can think of from my own experience is an interface called IClipboard:
IClipboard = interface
function CopyAvailable: Boolean;
function PasteAvailable(const Value: string): Boolean;
function CutAvailable: Boolean;
function SelectAllAvailable: Boolean;
procedure Copy;
procedure Paste(const Value: string);
procedure Cut;
procedure SelectAll;
end;
I have a bunch of custom controls derived from standard VCL controls. They each implement this interface. When a clipboard operation reaches one of my forms it looks to see if the active control supports this interface and, if so, dispatches the appropriate method.
For a very simple interface you can do this with an of object event handler, but once it gets sufficiently complex an interface works well. In fact I think that is a very good analogue. Use an interface where you a single of object event won't fit the functionality.
Interfaces solves a certain kind of issues. The primary function is to... well, ...define interfaces. To distinguish between definition and implementation.
When you want to specify or check if a class supports a set of methods - use interfaces.
You cannot do that in any other way.
(If all classes inherits from the same base class, then an abstract class will define the interface. But when you are dealing with different class hierarchies, you need interfaces to define the methods thy have in common...)
Extra note on
Cons: Performance
I think many people are too blithely dismissing the performance penalty of interfaces. (Not that I don't like and use interfaces but you should be aware of what you are getting into). Interfaces can be expensive not just for the _AddRef / _Release hit (even if you are just returning -1) but also that properties are REQUIRED to have a Get method. In my experience, most properties in a class have direct access for the read accessor (e.g., propery Prop1: Integer read FProp1 write SetProp1). Changing that direct, no penalty access to a function call can be significant hit on your speed (especially when you start adding 10s of property calls inside a loop.
For example, a simple loop using a class
for i := 0 to 99 do
begin
j := (MyClass.Prop1 + MyClass.Prop2 + MyClass.Prop3) / MyClass.Prop4;
MyClass.Update;
// do something with j
end;
goes from 0 function calls to 400 function calls when the class becomes an interface. Add more properties in that loop and it quickly gets worse.
The _AddRef / _Release penalty you can ameliorate with some tips (I am sure there are other tips. This is off the top of my head):
Use WITH or assign to a temp variable to only incur the penalty of one _AddRef / _Release per code block
Always pass interfaces using const keyword into a function (otherwise, you get an extra _AddRef / _Release occurs every time that function is called.
The only case when we had to use interfaces (besides COM/ActiveX stuff) was when we needed multiple inheritance and interfaces were the only way to get it. In several other cases when we attempted to use interfaces, we had various kinds of problems, mainly with reference counting (when the object was accessed both as a class instance and via interface).
So my advice would be to use them only when you know that you need them, not when you think that it can make your life easier in some aspect.
Update: As David reminded, with interfaces you get multiple inheritance of interfaces only, not of implementation. But that was fine for our needs.
Beyond what others already listed, a big pro of interfaces is the ability of aggregating them.
I wrote a blog post on that topic a while ago which can be found here: http://www.nexusdb.com/support/index.php?q=intf-aggregation (tl;dr: you can have multiple objects each implementing an interface and then assemble them into an aggregate which to the outside world looks like a single object implementing all these interfaces)
You might also want to have a look at the "Interface Fundamentals" and "Advanced Interface Usage and Patterns" posts linked there.
I'm using Delphi Pro 6. Right now, the only way to know if a class is missing a base class abstract method is to wait for the IDE to emit a "constructing instance of {derived class} containing abstract method {base class.abstract method name}" warning or to wait for a runtime Abstract Error method when an attempt to call the missing method is made. The former isn't sufficient since it only finds warnings for those derived classes actually constructed in the current project. The latter is just plain painful.
It would be so much better if Delphi output a fatal warning for all classes that do not declare/implement a base class abstract method immediately. Does anyone know a way to set this up or a plug-in that does this?
Thanks.
I've found the simplest way to do this is to add a section in the unit initialization area using a conditional define that creates an instance of each class that you think shouldn't have any abstract methods:
{$IFDEF CheckAbstracts}
initialization
TSubclass1.Create(params);
TAbstractClass1.Create(params); // Gives constructing instance of {derived class} containing abstract method warning
{$ENDIF}
Compile with the CheckAbstracts conditional, and you will get warnings whenever you have an incompletely implemented class.
A class containing abstract methods is only dangerous if you instantiate the class, so Delphi's warning is spot-on. You only get the abstract-error run time exception if you ignored at least one "instantiating class with abstract methods".
It's valid to not implement these methods. You might intend to implement the abstract method in yet another subtype.
A later version of Delphi/Win32 (I don't remember which) introduced formal abstract classes, which make it clear when you do and do not intend to instantiate the type. If you're rigorous about using this, the feature you request would then make sense. But for D6 it is not clear.