What's the best practice to work with ENUM in Intersystems Caché?

Natively, Caché doesn't implement ENUMs such as Java for example, when you need to implement a solution like the following example in Java, but in Caché, what are the best practices?

public enum Planet {
    MERCURY (3.303e+23, 2.4397e6),
    VENUS   (4.869e+24, 6.0518e6),
    EARTH   (5.976e+24, 6.37814e6),
    MARS    (6.421e+23, 3.3972e6),
    JUPITER (1.9e+27,   7.1492e7),
    SATURN  (5.688e+26, 6.0268e7),
    URANUS  (8.686e+25, 2.5559e7),
    NEPTUNE (1.024e+26, 2.4746e7);

    private final double mass;   // in kilograms
    private final double radius; // in meters
    Planet(double mass, double radius) {
        this.mass = mass;
        this.radius = radius;
    } 
    private double mass() { return mass; }
    private double radius() { return radius; }
}

final Planet mars = Planet.MARS;

Access to the code as simply Planet.MARS

Upvotes: 3

Views: 1002

Answers (2)

DAiMor
DAiMor

Reputation: 3205

Example on calculable parameters

Class so.Enum Extends %RegisteredObject
{

Parameter MERCURY As COSEXPRESSION = "..%New(3.303e+23, 2.4397e6)";

Parameter VENUS As COSEXPRESSION = "..%New(4.869e+24, 6.0518e6)";

Parameter EARTH As COSEXPRESSION = "..%New(5.976e+24, 6.37814e6)";

Parameter MARS As COSEXPRESSION = "..%New(6.421e+23, 3.3972e6)";

Parameter JUPITER As COSEXPRESSION = "..%New(1.9e+27,   7.1492e7)";

Parameter SATURN As COSEXPRESSION = "..%New(5.688e+26, 6.0268e7)";

Parameter URANUS As COSEXPRESSION = "..%New(8.686e+25, 2.5559e7)";

Parameter NEPTUNE As COSEXPRESSION = "..%New(1.024e+26, 2.4746e7)";

Property Mass As %Double;

Property Radius As %Double;

Method %OnNew(mass, radius) As %Status
{
    set ..Mass=mass
    set ..Radius=radius
    quit $$$OK
}

}

and, you can use it so

USER>w ##class(so.Enum).#MERCURY.Mass
330300000000000000000000
USER>w ##class(so.Enum).#MERCURY.Radius
2439700
USER>w ##class(so.Enum).#MERCURY.Radius
2439700
USER>w ##class(so.Enum).#EARTH.Radius
6378140
USER>w ##class(so.Enum).#EARTH
[email protected]
USER>w ##class(so.Enum).#MERCURY
[email protected]

and you can define it as a macros

#define MERCURY ##class(so.Enum).#MERCURY

or

#define Planet(%planet) $parameter("so.Enum",$zcvt("%planet","U"))

Upvotes: 5

user3532194
user3532194

Reputation: 51

I have never done something like this before with cache but I guess you can do something like this: (Ab)using the dynamic dispatching of propertys.

Class TST.Planet Extends %RegisteredObject  
{

  Property Mass As %Library.Double;
  Property Radius As %Library.Double;

  /// Property dispatch method to catch references to 
  /// virtual properties.<br>
  /// This should not be called directly.<br>
  Method %DispatchGetProperty(pProperty As %String) [ Final, Internal ]
  {
        #Dim Planets As %Library.String // multidimensional
        s Planets("MERCURY")=3.303e+23_"\"_2.4397e6
        s Planets("VENUS")=4.869e+24_"\"_6.0518e6
        s Planets("EARTH")=5.976e+24_"\"_6.37814e6
        s Planets("MARS")=6.421e+23_"\"_3.3972e6
        s Planets("JUPITER")=1.9e+27_"\"_7.1492e7
        s Planets("SATURN")=5.688e+26_"\"_6.0268e7
        s Planets("URANUS")=8.686e+25_"\"_2.5559e7
        s Planets("NEPTUNE")=1.024e+26_"\"_2.4746e7
        if $DATA(Planets(pProperty)) {
          s result = ##class(TST.Planet).%New()
          s result.Mass=$PIECE(Planets(pProperty),"\",1)
           s result.Radius=$PIECE(Planets(pProperty),"\",2)
          q result
        }
      }
  }

You then have to use it like this:

s x = ##Class(TST.Planet).%New()
s x = x.MARS
zw x

EDIT: can also do s x =##Class(TST.Planet).%New().MARS

And get this result:

x=<OBJECT REFERENCE>[[email protected]]
+----------------- general information ---------------
|      oref value: 2
|      class name: TST.Planet
| reference count: 2
+----------------- attribute values ------------------
|               Mass = 642100000000000000000000
|             Radius = 3397200

Upvotes: 0

Related Questions