Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2010-10

Problem accessing Class Method with abstraction

6 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Andrew Brunner

I've got a class factory problem I'm trying to resolve and it appears I'm at a point where it's probably better to ask for help.

  TCoreObjects=class;
  TCoreObject=Class (TPersistent)
  protected
    class procedure VerifyIDs(var Module:TDBMSModule); Virtual; abstract;
  end;
  TAdminCore=Class(TCoreObject)
  protected
    class procedure VerifiyIDs(var Module:TDBMSModule); override;
  end;

<SNIP>

procedure VerifyIDs(Var Module:TDBMSModule);
var
  iLcv:integer;
  ItemP:PCoreObjectItem; // Just record storing classname to load and
(each core object implment is loaded just not detailed here for
simplicity)
  coGeneric:TPersistentClass;
  coItem:TCoreObject;
begin
  for iLcv:=0 to High(CoreObjectItems) do begin
    ItemP:=CoreObjectItems[iLcv];
    coGeneric:=GetClass(ItemP^.ClassName);
    if (coGenericnil) and coGeneric.InheritsFrom(TCoreObject) then begin
      coItem:=coGeneric as TCoreObject << COMPILER ERROR :-(
      TPersistentClass(coItem):=coGeneric; << Compiles but get Runtime Error
      coItem.VerifyIDs(Module); < CRASH @ RUNTIME
    end;
  end;
end;

How can I get each class's implement of VerifyIDs to get called as each one is different but yet single.

Reply by email

patspiper
to Andrew Brunner
Andrew Brunner wrote 30 lines
I've got a class factory problem I'm trying to resolve and it appears I'm at a point where it's probably better to ask for help. TCoreObjects=class; TCoreObject=Class (TPersistent) protected class procedure VerifyIDs(var Module:TDBMSModule); Virtual; abstract; end; TAdminCore=Class(TCoreObject) protected class procedure VerifiyIDs(var Module:TDBMSModule); override; end; <SNIP> procedure VerifyIDs(Var Module:TDBMSModule); var iLcv:integer; ItemP:PCoreObjectItem; // Just record storing classname to load and (each core object implment is loaded just not detailed here for simplicity) coGeneric:TPersistentClass; coItem:TCoreObject; begin for iLcv:=0 to High(CoreObjectItems) do begin ItemP:=CoreObjectItems[iLcv]; coGeneric:=GetClass(ItemP^.ClassName); if (coGenericnil) and coGeneric.InheritsFrom(TCoreObject) then begin coItem:=coGeneric as TCoreObject<< COMPILER ERROR :-(

coItem is an object while coGeneric is a class

TPersistentClass(coItem):=coGeneric;<< Compiles but get Runtime Error

same as above

Show quoted text 8 lines
coItem.VerifyIDs(Module);< CRASH @ RUNTIME end; end; end; How can I get each class's implement of VerifyIDs to get called as each one is different but yet single.
Maybe using:
procedure TCoreObject.VerifyIDs(Var Module:TDBMSModule);
procedure TAdminCore.VerifyIDs(Var Module:TDBMSModule);

Reply by email

Michael Van Canneyt
to Andrew Brunner: I've got a class factory problem I'm trying to resolve and it appears I'm at a point…
Andrew Brunner wrote 29 lines
I've got a class factory problem I'm trying to resolve and it appears I'm at a point where it's probably better to ask for help. TCoreObjects=class; TCoreObject=Class (TPersistent) protected class procedure VerifyIDs(var Module:TDBMSModule); Virtual; abstract; end; TAdminCore=Class(TCoreObject) protected class procedure VerifiyIDs(var Module:TDBMSModule); override; end; <SNIP> procedure VerifyIDs(Var Module:TDBMSModule); var iLcv:integer; ItemP:PCoreObjectItem; // Just record storing classname to load and (each core object implment is loaded just not detailed here for simplicity) coGeneric:TPersistentClass; coItem:TCoreObject; begin for iLcv:=0 to High(CoreObjectItems) do begin ItemP:=CoreObjectItems[iLcv]; coGeneric:=GetClass(ItemP^.ClassName); if (coGenericnil) and coGeneric.InheritsFrom(TCoreObject) then begin coItem:=coGeneric as TCoreObject << COMPILER ERROR :-(

Of course it errors, you're trying to store a VMT in an object instance.

You chould declare

   TCoreObjectClass = Class (TCoreObject);
and
   coItem : TCoreObjectClass;

Then

   coItem:=TCoreObjectClass(coGeneric);
   coItem.VerifyIDs(Module);

Should work. Untested (not enough code provided) but I think the above should work.

Michael.

Reply by email

Andrew Brunner
to Michael Van Canneyt

On Sun, Oct 17, 2010 at 3:33 AM, Michael Van Canneyt wrote:

<SNIP>
// Revised code
CCoreObject=Class(TCoreObject);
TCoreObjects=class;
TCoreObject=Class (TPersistent)
 protected
   class procedure VerifyIDs(var Module:TDBMSModule); Virtual; abstract;
 end;
 TAdminCore=Class(TCoreObject)
 protected
   class procedure VerifiyIDs(var Module:TDBMSModule); override;
 end;
procedure TCoreObjects.Load;
var
  iLcv:integer;
  coGeneric:TPersistentClass;
  ItemP:PCoreObjectItem;
  coItem:TCoreObject;
  id:IStringsAdapter;
begin
  if FInfo.Loaded then exit;
  for iLcv:=0 to High(CoreObjectItems) do begin
    ItemP:=CoreObjectItems[iLcv];
    coGeneric:=GetClass(ItemP^.ClassName);
    if (coGenericnil) then
      Add(iLcv,coGeneric);
  end;
  FInfo.Loaded:=True;
end;
procedure TCoreObjects.Add(iCoreItemIndex:integer; Item:TPersistentClass);
var
  iIndex:integer;
  coItem:TCoreObject;
begin
  if Item.InheritsFrom(TCoreObject) then begin
    coItem:=Item.Create as TCoreObject;
    iIndex:=Add(coItem);
    Copy(CoreObjectItems[iCoreItemIndex]^,coItem.Header);
    ;
    coItem.Initialize;
  end;
end;

<OMITTED>

procedure VerifyIDs(Var Module:TDBMSModule);
var
  iLcv:integer;
  ItemP:PCoreObjectItem;
  coGeneric:TPersistentClass;
  coItem:CCoreObject;
begin
  for iLcv:=0 to High(CoreObjectItems) do begin
    ItemP:=CoreObjectItems[iLcv];
    coGeneric:=GetClass(ItemP^.ClassName);
    if (coGenericnil) and coGeneric.InheritsFrom(TCoreObject) then begin
      // coItem:=coGeneric as CCoreObject; // did not compile
      coItem:=TCoreObjectClass(coGeneric); // Compiles
      coItem.VerifyIDs(Module); // SIGEV
    end;
  end;
end;

It's crashing with SIGEV error. I think b/c at that point the class reference becomes a TCoreObjectClass with pointer to abstracted method not the TAdminCore.VerifyIDs method.

Take TCoreObjects.Add(iCoreItemIndex:integer; Item:TPersistentClass); for a point of discussion... It has no problems loading and creating instances of descendant core objects as they are presently running and referenced throughout the project. So while this method accepts the as TCoreObject the as keyword does not work for class references. How can I leave these class references as generic but yet still access the implmented method of the descendant class?

Reply by email

Andrew Brunner
to Andrew Brunner
procedure VerifyIDs(Var Module:TDBMSModule);
var
  iLcv:integer;
  ItemP:PCoreObjectItem;
  coGeneric:TPersistentClass;
  coItem:TCoreObject;
begin
  for iLcv:=0 to High(CoreObjectItems) do begin
    ItemP:=CoreObjectItems[iLcv];
    coGeneric:=GetClass(ItemP^.ClassName);
    if (coGenericnil) and coGeneric.InheritsFrom(TCoreObject) then begin
      coItem:=coGeneric.Create as TCoreObject;
      Try
        coItem.VerifyIDs(Module);
      finally
        FreeAndNil(coItem);
      end;
    end;
  end;
end;

This code works as expected but why do I need to create an instance of the object if I just want to reference it's class procedure of VerifyIDs?

Reply by email

Andrew Hall
to Andrew Brunner

The reason you cannot call VerifyID's from coGeneric is that the compiler sees coGeneric as a TPersistentClass which does not implement the VerifyIDs method. The following changes will give you the desired result...

type
  TCoreObjectClass = class of TCoreObject;
If (coGenericnil) and coGeneric.InheritsFrom(TCoreObject) then
  TCoreObjectClass(coGeneric).VerifyIDs(Module);

Regards Andrew.

Andrew Brunner wrote 27 lines
procedure VerifyIDs(Var Module:TDBMSModule); var iLcv:integer; ItemP:PCoreObjectItem; coGeneric:TPersistentClass; coItem:TCoreObject; begin for iLcv:=0 to High(CoreObjectItems) do begin ItemP:=CoreObjectItems[iLcv]; coGeneric:=GetClass(ItemP^.ClassName); if (coGenericnil) and coGeneric.InheritsFrom(TCoreObject) then begin coItem:=coGeneric.Create as TCoreObject; Try coItem.VerifyIDs(Module); finally FreeAndNil(coItem); end; end; end; end; This code works as expected but why do I need to create an instance of the object if I just want to reference it's class procedure of VerifyIDs? _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email