Как лучше всего работать с ENUM в Intersystems Caché?
Собственно, Caché не реализует ENUM, например Java, когда вам нужно реализовать решение, подобное следующему примеру на Java, но в Caché, каковы лучшие практики?
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;
Доступ к коду так же просто Planet.MARS
2 ответа
Решение
Пример вычисляемых параметров
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
}
}
и вы можете использовать его так
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
1@so.Enum
USER>w ##class(so.Enum).#MERCURY
1@so.Enum
и вы можете определить это как макрос
#define MERCURY ##class(so.Enum).#MERCURY
или же
#define Planet(%planet) $parameter("so.Enum",$zcvt("%planet","U"))
Я никогда раньше не делал что-то подобное с кешем, но думаю, что вы можете сделать что-то вроде этого: (Ab) используя динамическую диспетчеризацию свойств.
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
}
}
}
Затем вы должны использовать это так:
s x = ##Class(TST.Planet).%New()
s x = x.MARS
zw x
EDIT: can also do s x =##Class(TST.Planet).%New().MARS
И получить этот результат:
x=<OBJECT REFERENCE>[2@TST.Planet]
+----------------- general information ---------------
| oref value: 2
| class name: TST.Planet
| reference count: 2
+----------------- attribute values ------------------
| Mass = 642100000000000000000000
| Radius = 3397200