0

Given the following code:

type
  Class1 = public class
  end;

  Class1Class = class of Class1;

  Class2 = public class (Class1)
  end;

  Class3 = public class (Class1)
  end;

  Class4 = public class
  public
    method DoSomething(c: Class1Class): Integer;
  end;

implementation

method Class4.DoSomething(c: Class1Class): Integer;
begin
  if c = Class2 then
    result := 0
  else if c = Class3 then
    result := 1
  else
    result := 2;
end;

How should DoSomething actually be written, as the equality comparisons throw the compiler error: Type mismatch, cannot find operator to evaluate "class of Class1" = "<type>"

Using is compiles, but in actuality the first conditional always evaluates to true no matter if Class2 or Class3 is passed in.

The goal is to write this in a cross-platform ways without using code specific to any one of the platforms Oxygene supports.

jep
  • 747
  • 6
  • 25

2 Answers2

0

You must create class references for each class used in the conditionals and use the is operator.

type
  Class1 = public class
  end;

  Class1Class = class of Class1;

  Class2 = public class (Class1)
  end;

  Class3 = public class (Class1)
  end;

  Class4 = public class
  public
    method DoSomething(c: Class1Class): Integer;
  end;

  Class2Class = class of Class2;
  Class3Class = class of Class3;

implementation


method Class4.DoSomething(c: Class1Class): Integer;
begin
  if c is Class2Class then
    result := 0
  else if c is Class3Class then
    result := 1
  else
    result := 2;
end;
jep
  • 747
  • 6
  • 25
0

I am not sure why you are testing the class type specifically - ths should not be necessary if you are virtualising the behaviours of the class via the class reference, but assuming you have reasons for needing to work with class identity of a class reference...

You do not say which platform you are working on, but on Java the Java class types work quite well for these purposes, without needing to use Oxygene class references:

method Class4.DoSomething(c: &Class<Object>): Integer;
begin
  case c of
    typeOf(Class2): result := 0;
    typeOf(Class3): result := 1;
  else
    result := 2;
  end;
end;


// Examples of usage:

c4.DoSomething(typeOf(Class1));

someC := new Class3;
c4.DoSomething(someC.Class);

If you are not working on Java or need a platform-portable approach, then you could incorporate an alternate class identity in the classes using virtual class methods:

  Class1 = public class
    class method classID: Integer; virtual;
  end;

Implement this to return some constant identifying Class1. Override in descendant classes to return an appropriate ID for each class. Then in your DoSomething method:

method Class4.DoSomething(c: Class1Class): Integer;
begin
  case c.classID of
    CLASS_2: result := 0;
    CLASS_3: result := 1;
  else
    result := 2;
  end;
end;
Deltics
  • 22,162
  • 2
  • 42
  • 70
  • I updated the question to reflect that I'm trying to keep it cross-platform compatible. As far as the "why", that's really beyond the scope of the question. I prefer to answer the question (my own, in this case) rather than say "rewrite your code." Practice is always much more complicated than theory, and I assume people could rewrite the code on their own. Personally, your solution seems a bit more clunky and less elegant than what I'm doing. I can't figure out how it'd actually be better rather than just different. – jep Oct 14 '13 at 14:03
  • "Why" is rarely beyond the scope. If what you need to do can be achieved using virtualised behaviour on the class itself (cross-platform by nature) then the opportunities for such errors can be reduced or removed entirely and then the question of class identity becomes moot. Relying on class identity means that anywhere that your code needs to vary it's behaviour based on class identity will need to be updated every time you add a new class, introducing the possibility of introducing errors (of omission) in the future. But you are happy with your approach, so fair enough. :) – Deltics Oct 14 '13 at 19:33
  • Well, the place I ran into it was in a block of debugging/logging code I was running. So yes, quite happy. :) – jep Oct 14 '13 at 21:01