Why can't I use "is" on a class reference type? lazarus / 62-General ---------------------------------------------------------------------- ahydra · 2017-03-11 15:40 Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  type  TA = class    ...  end;   TB = class(TA)    ...  end;   TAClass = class of TA; function IsB(aType: TAClass): boolean;  begin    Result := (aType is TB); // won't compile: Class or COM interface type expected, but got "TAClass"end;   (Lazarus 1.6.4, FPC 3.0.2) Why is this not possible? Since all the "is" operator does is compare the VMT pointer given by the RHS to the VMT pointer of the class instance on the LHS (and recurse through its parents until there's a match), it should also be possible to do the same thing with VMT pointers in the form of class reference types. Thanks, ahydra ---------------------------------------------------------------------- Thaddy · 2017-03-11 15:49 A class reference is not a class.It is as simple as that. Try: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function IsB(aType: TAClass): boolean;  begin    Result := (aType = TB.ClassType); // just compare the class referencesend; A bit nicer is this (untested): Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i operator = (const a:TClass;const b:Tobject) c:boolean;inline;begin  c := (a=b.classtype);end; operator i = (const a:Tobject;const b:TClass) c:Boolean;inline;begin  c := (a.classtype = b);end; ---------------------------------------------------------------------- sky_khan · 2017-03-11 16:57 I think you're looking for "InheritsFrom", Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   Result:=aType.InheritsFrom(TB); ---------------------------------------------------------------------- howardpc · 2017-03-11 16:59 Yes. In the following program, the function IsAClass(aClassRef: TBClass) is pretty useless, since no TBClass (TB being declared as other than TA) can ever be a TAClass, i.e. the outcome of the function is always known in advance, so it hardly adds any useful information. Potentially more useful is whether TA and TB are related, viz. the DescendsFromA function. Note that (unlike your function IsB) the parameter is a general TClass, which makes the applicabiity of the the wrapped  InheritsFrom() function much wider than just to TAClass classes. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program project1; {$mode objfpc} type  TA = class end;  TB = class(TA) end; TBClass = class of TB; function IsAClass(aClassRef: TBClass): boolean;begin  Result:=(aClassRef = TA.ClassType);end; function DescendsFromA(aClassRef: TClass): Boolean;begin  Exit(aClassRef.InheritsFrom(TA));end; begin  WriteLn('IsAClass(TB) is ',IsAClass(TB));  WriteLn('DescendsFromA(TB) is ',DescendsFromA(TB));  ReadLn;end. ---------------------------------------------------------------------- ahydra · 2017-03-11 17:03 Fair enough - TB is a type rather an a VMT pointer, so you need to call ClassType on it to get the VMT pointer. However Thaddy's solution doesn't take care of inheritance (a class reference variable set to a subclass of TB should also return true for "is TB"). Here's what I came up with: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program Project1; uses sysutils; type  TA = class   end;   TB = class(TA)   end;   TC = class(TB)   end;   TD = class(TA)   end;   TAClass = class of TA; function ClassReferenceIs(aObjectClass, aTargetClass: TAClass): boolean;  type    PVMT = ^TVMT;    TVMT = packed record      Useless: ptruint;      Useless2: ptruint;      AncestorVMT: pointer;    end;   var    p: pointer;   begin    p := pointer(aObjectClass);     repeat    if p = pointer(aTargetClass) then      begin        Result := true;        exit;      end;       p := PVMT(p)^.AncestorVMT;    until p = nil;     Result := false;end; var  AC: TAClass; begin  AC := TA;  writeln(booltostr(ClassReferenceIs(AC, TB), 'yep', 'nope')); // nope  AC := TB;  writeln(booltostr(ClassReferenceIs(AC, TB), 'yep', 'nope')); // yep  AC := TC;  writeln(booltostr(ClassReferenceIs(AC, TB), 'yep', 'nope')); // yep  AC := TD;  writeln(booltostr(ClassReferenceIs(AC, TB), 'yep', 'nope')); // nope   readln(); end.  I think to be honest though, FPC should support "is" on class references. It's a perfectly sensible thing to want to do, and can use exactly the same algorithm as for class instances. In fact, it should probably support things like "TB is TA" as well? That may be rather useless, but it still makes sense - when compiling, the type "TB" used as a value is just the VMT pointer of TB. I see now two people have suggested InheritsFrom, that works wonderfully - thanks. ahydra