-1

I have a system in Delphi 7 with zeos 6 in which I use the following function:

function zIncCodeByYear (zQry : TZquery; ....): String;
var
  zConLocal, zConOriginal : TZConnection;
  ... 
begin
  bActive := zQry.Active;
  zConOriginal :=  zQry.Connection;

This always worked fine, Now I need to convert this system to Delphi Seatle and, consequently, to Zeos trunk (7.2), after to install this version, in time compile, I get the error:

[dcc32 Error] zeosfuncs.pas(265): E2010 Incompatible types: 'TZConnection' and 'TZAbstractConnection'

What happens? How to get the connection from zquery in this version?

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
Sidon
  • 1,316
  • 2
  • 11
  • 26

2 Answers2

0

You haven't really provided much code. But presumably Zeos changed the type of TZQuery.Connection to TZAbstractConnection. So it should suffice for you to change your local variable declaration as follows:

var
  zConLocal, zConOriginal : TZAbstractConnection;

And also remember the principle: Program to an interface, not an implementation (Unfortunately the accepted answer on that question is brilliantly amusing, but wrong. At least the answer I linked is correct.)

Disillusioned
  • 14,635
  • 3
  • 43
  • 77
  • @Sidon Did you even bother to try what I advised? Hard-casting as you have done is a bad idea and leads to serious errors when you get it wrong. You can typecast a more safely using `(zQry.Connection as TZConnection);` but with my suggestion you wouldn't need typecasting _at all_! Also: if my suggestion doesn't work, then the types are incompatible meaning that although your forced typecasting may compile the underlying object is different; this means some of the things you try to do to it are likely to fail spectacularly. As an analogy, you can't take a microwave and drive the streets. – Disillusioned Jul 21 '17 at 03:38
  • 1
    @Sidon Do you understand the principles of class hierarchies? Although you haven't shown the code it's very probable that TZConnection is declared as: `TZConnection = class(TZAbstractConnection)...` This means variable of type `TZAbstractConnection` can reference objects of type `TZConnection`. Certainly `zQry.Connection` is of type `TZAbstractConnection` _which is exactly what your error message tells you_! Right-click on "Connection" in in `zQry.Connection`; click "Find declaration"; and you should be taken to the line of code that confirms this. – Disillusioned Jul 21 '17 at 03:55
  • 1
    @Sidon Finally, before you ***claim*** someone is "totally wrong"; you may want to at least ***try it*** or make sure you understand it. Behaving like an arrogant thug because you managed to hack out a ***very bad alternative*** solution is not a good way to learn. – Disillusioned Jul 21 '17 at 03:57
  • Bad idea is to continue this flame. Relax. All the best! – Sidon Jul 21 '17 at 11:37
  • @Craig The properties are available in the public section in TZAbstractConnection. So your suggestion works of course. The ZEOS guys will have considered that case. I personally tend to think of TZConnection as a very general example for a custom connection provided by the developer too. –  Jul 22 '17 at 17:31
  • @AplikmUj What properties are available on `TZAbstractConnection` is hardly relevant to the question as Sidon omitted the code that uses `zConOriginal`. We can only guess it's purpose which could be only to hold the ref temporarily. However, what you say is to be expected because it's the stock standard approach with any abstract base class.… The base class (in this case `TZAbstractConnection`) defines the _interface_ i.e. what properties/methods _can be_ called. And concrete subclasses (e.g. `TZConnection`) define the _implementation_ i.e. _how_ to carry out the responsibilities. – Disillusioned Jul 23 '17 at 05:01
  • Also it's better for other classes (such as `TZQuery`) to reference the abstract base class instead of a specific implementation. This enables these other classes to work with other types of connection (hypothetical e.g. `TZSoapConnection`). It seems the ZEOS team made this improvement in ver 7.2). The point that @Sidon seems uninterested in learning is that a variables of a base class type can reference object instances of a subclass type. That's his loss - it doesn't affect me. Apparently he doesn't like being corrected; hence his unsavoury behaviour an hallucinations of flaming. – Disillusioned Jul 23 '17 at 05:19
  • 1
    @Craig, Ok Man! Sorry if I looked rude. I will study your solution. Again: All the best. Sincerely. – Sidon Jul 23 '17 at 14:17
  • @Craig The reason why there is separated TZQuery seems to be about having an opportunity to store passwords encrypted for example. I personally, even if this discussion goes beyond the original question, put such a behavior an subcall TZAbstractConnection which is not the 'TCustomClassXYZ'. The design of DBConnections in case of having to consider multiple target databases have always been a hot topic concerning extensibilty - the wish list never ends. In such a case using an abstract class will not help. In general I totally agree with what you said. –  Jul 23 '17 at 21:18
0

You can simply use ZAbstractConnection and casting to TZConnection does not make a difference for you. Whatever you do is not wrong in this specific case.

With the help of TZConnection a few properties such as Database, Protocol, ... are being published. In the base class TZAbstractConnection those are public.