1. Diferencia entre métodos de instancia y métodos de clase (Method vs ClassMethod, sintaxis ..property)
Puntos Clave
- Method: Método de instancia que opera sobre una instancia de objeto específica; tiene acceso a propiedades vía `..PropertyName`
- ClassMethod: Se invoca sobre la clase misma sin requerir una instancia de objeto
- Los métodos de instancia reciben una referencia implícita `%This` al objeto actual
- La sintaxis ..PropertyName accede a las propiedades de la instancia actual (solo en métodos de instancia)
- Los métodos de clase no pueden usar la sintaxis `..` porque no hay instancia de objeto
Notas Detalladas
Descripción general
InterSystems IRIS distingue entre dos tipos fundamentales de métodos. La elección entre ellos determina cómo se invoca el método y a qué datos puede acceder. Esta distinción es crítica para el diseño correcto de clases.
Métodos de Instancia
Class Sample.Person Extends %Persistent
{
Property Name As %String;
Property DOB As %Date;
/// Instance method - operates on a specific person
Method GetAge() As %Integer
{
Set today = +$HOROLOG
Set birthDays = ..DOB
Return (today - birthDays) \ 365.25
}
/// Instance method that modifies the object
Method UpdateName(newName As %String) As %Status
{
Set ..Name = newName
Return ..%Save()
}
}
Llamar a un método de instancia requiere una referencia de objeto:
Set person = ##class(Sample.Person).%OpenId(1)
Set age = person.GetAge()
Write "Age: ", age, !
Métodos de Clase
Class Sample.Person Extends %Persistent
{
/// Class method - no object instance needed
ClassMethod FindByName(name As %String) As Sample.Person
{
&sql(SELECT ID INTO :id FROM Sample.Person WHERE Name = :name)
If SQLCODE = 0 {
Return ##class(Sample.Person).%OpenId(id)
}
Return ""
}
/// Class method - utility function
ClassMethod GetCount() As %Integer
{
&sql(SELECT COUNT(*) INTO :count FROM Sample.Person)
Return count
}
}
Llamar a un método de clase usa la sintaxis de referencia de clase:
Set person = ##class(Sample.Person).FindByName("John Smith")
Set total = ##class(Sample.Person).GetCount()
La Sintaxis ..
La sintaxis de doble punto es azúcar sintáctico disponible solo en métodos de instancia:
..PropertyNameaccede a una propiedad (equivalente a$THIS.PropertyName)..MethodName()llama a otro método de instancia sobre el mismo objeto..#ParameterNameaccede a un parámetro de clase (funciona tanto en métodos de instancia como de clase)
Method DisplayInfo()
{
Write "Name: ", ..Name, !
Write "Age: ", ..GetAge(), ! // calls instance method
Write "Type: ", ..#OBJECTTYPE, ! // accesses class parameter
}
Cuándo Usar Cada Tipo
| Usar Método de Instancia Cuando... | Usar ClassMethod Cuando... |
|---|---|
| Se opera sobre los datos de un objeto específico | No se necesita un objeto específico |
| Se accede o modifica propiedades | Se realizan búsquedas o consultas |
| Se computan valores derivados de propiedades | Se crean métodos de fábrica |
| Se implementa lógica de negocio para un objeto | Se implementan funciones utilitarias |
Referencias de Documentación
2. Usa parámetros de clase dentro de métodos (..#ParameterName)
Puntos Clave
- ..#ParameterName accede a un parámetro de clase desde cualquier método (instancia o clase)
- Los parámetros de clase actúan como constantes definidas a nivel de clase
- Los parámetros pueden sobrescribirse en subclases, habilitando comportamiento polimórfico
- Parámetros comunes del sistema: DEFAULTGLOBAL, USEEXTENTSET, MANAGEDEXTENT
- Usar parámetros para valores de configuración que pueden variar por subclase
Notas Detalladas
Descripción general
Los parámetros de clase definen constantes asociadas a una clase. Proporcionan una forma de configurar el comportamiento de la clase sin codificar valores de forma fija en los métodos. Dado que los parámetros pueden sobrescribirse en subclases, habilitan un patrón poderoso donde los métodos de la clase base adaptan su comportamiento según la configuración de la subclase.
Definición y Acceso a Parámetros
Class Sample.Notification Extends %RegisteredObject
{
Parameter MAXRETRIES = 3;
Parameter TIMEOUT = 30;
Parameter PROVIDER = "Email";
Method Send(message As %String) As %Status
{
For i = 1:1:..#MAXRETRIES {
// Attempt to send with timeout
Set sc = ..DoSend(message, ..#TIMEOUT)
If $$$ISOK(sc) Return sc
}
Return $$$ERROR($$$GeneralError, "Failed after " _ ..#MAXRETRIES _ " retries")
}
ClassMethod GetProvider() As %String
{
Return ..#PROVIDER
}
}
Sobrescritura de Parámetros en Subclases
Class Sample.SMSNotification Extends Sample.Notification
{
Parameter MAXRETRIES = 5;
Parameter TIMEOUT = 10;
Parameter PROVIDER = "SMS";
}
Cuando SMSNotification.Send() se ejecuta, ..#MAXRETRIES evalúa a 5 y ..#TIMEOUT a 10 (los valores sobrescritos), aunque el código del método esté definido en la clase padre. Esto se resuelve en tiempo de compilación.
Tipos de Parámetros
Los parámetros pueden tener opcionalmente una restricción de tipo:
Parameter BATCHSIZE As %Integer = 100;
Parameter ENABLED As %Boolean = 1;
Parameter PREFIX As %String = "APP";
Parámetros Comunes del Sistema
Varios parámetros del sistema controlan el comportamiento de las clases:
| Parámetro | Propósito |
|---|---|
| USEEXTENTSET | Usar nombres de globals con hash para el almacenamiento |
| MANAGEDEXTENT | Permitir que %ExtentMgr rastree la extensión |
| DEFAULTGLOBAL | Sobrescribir el nombre de global por defecto para almacenamiento |
| READONLY | Prevenir la modificación de objetos |
| DSTIME | Habilitar la sincronización BI |
Uso de Parámetros para Comportamiento Configurable
Class Sample.BaseProcessor Extends %RegisteredObject
{
Parameter LOGPREFIX = "PROC";
Parameter LOGLEVEL = 2;
Method Log(message As %String, level As %Integer = 1)
{
If level <= ..#LOGLEVEL {
Write "[", ..#LOGPREFIX, "] ", message, !
}
}
}
Referencias de Documentación
3. Especifica argumentos de método y tipo de retorno (cláusula As, Output, ByRef)
Puntos Clave
- As ClassName especifica el tipo de retorno de un método
- Los argumentos del método se declaran con nombre, tipo opcional y valor por defecto opcional
- La palabra clave Output indica que el argumento es solo de salida (no se pasa como entrada)
- La palabra clave ByRef indica que el argumento se pasa por referencia (tanto entrada como salida)
- Importante: `ByRef` y `Output` en la lista de parámetros formales son puramente indicativos — no tienen efecto intrínseco en cómo se pasa el argumento. Es el llamador quien decide usando el prefijo punto (`.`). El método funcionaría igual incluso sin `ByRef`/`Output` en la firma.
- Los valores por defecto se especifican con `= value` en la lista de argumentos
Notas Detalladas
Descripción general
Las firmas de métodos bien definidas mejoran la claridad del código, habilitan mejor verificación en tiempo de compilación y generan documentación precisa. InterSystems IRIS soporta argumentos tipados, tipos de retorno, valores por defecto y parámetros por referencia.
Firma Básica de Método
Method Calculate(x As %Numeric, y As %Numeric) As %Numeric
{
Return x + y
}
El As %Numeric después del paréntesis de cierre especifica el tipo de retorno. Los tipos de argumentos siguen a cada nombre de argumento.
Valores por Defecto
Method FormatDate(date As %Date, format As %String = "YYYY-MM-DD") As %String
{
// format defaults to "YYYY-MM-DD" if not provided
Return $ZDate(date, 3)
}
Llamando con o sin el parámetro opcional:
Set result = obj.FormatDate($HOROLOG) // uses default format
Set result = obj.FormatDate($HOROLOG, "MM/DD") // overrides default
Parámetros Output
La palabra clave Output marca un argumento como solo de salida. El llamador no debe pasar un valor; el método lo establecerá:
ClassMethod Divide(a As %Numeric, b As %Numeric, Output result As %Numeric) As %Status
{
If b = 0 Return $$$ERROR($$$GeneralError, "Division by zero")
Set result = a / b
Return $$$OK
}
Llamando con un parámetro de salida (usar el prefijo punto):
Set sc = ##class(Sample.Math).Divide(10, 3, .answer)
If $$$ISOK(sc) Write "Result: ", answer, !
Parámetros ByRef
La palabra clave ByRef marca un argumento como pasado por referencia. La variable del llamador se lee y se modifica:
ClassMethod Increment(ByRef counter As %Integer, amount As %Integer = 1)
{
Set counter = counter + amount
}
Llamando:
Set myCount = 5
Do ##class(Sample.Util).Increment(.myCount, 3)
Write myCount // Outputs: 8
Distinción Clave: Output vs ByRef
| Aspecto | Output | ByRef |
|---|---|---|
| Valor inicial pasado como entrada | No (indefinido dentro del método) | Sí (valor del llamador disponible) |
| Valor devuelto al llamador | Sí | Sí |
| Sintaxis del llamador | .variable | .variable |
| Significado semántico | El método produce un valor | El método lee y modifica un valor |
Importante: ByRef y Output Son Puramente Indicativos
En ObjectScript, ByRef y Output en la lista de parámetros formales son solo indicaciones de documentación — no tienen efecto de aplicación ni en tiempo de ejecución. El mecanismo de paso se controla enteramente por el llamador usando el prefijo punto (.).
Esto significa:
- Un llamador puede usar
.variableincluso si el parámetro no está declarado comoByRefuOutput— y funciona - Un llamador puede omitir el punto incluso si el parámetro está declarado como
ByRef— y simplemente se pasa por valor - Podría eliminar
ByRef/Outputde cada firma de método y todo seguiría funcionando idénticamente
/// No ByRef or Output keyword — but pass-by-reference still works!
ClassMethod AddSuffix(text As %String, suffix As %String)
{
Set text = text _ suffix
}
Set myText = "Hello"
Do ##class(Sample.Util).AddSuffix(.myText, " World")
Write myText // "Hello World" — modified despite no ByRef in signature!
Mejor práctica: Siempre declarar ByRef u Output en la firma como documentación para el llamador, aunque las palabras clave en sí no tengan efecto. Señalan el contrato previsto del método.
Métodos que Devuelven %Status
Un patrón común es devolver %Status y usar parámetros Output para los resultados reales:
ClassMethod ProcessData(input As %String, Output result As %String, Output errorMsg As %String) As %Status
{
If input = "" {
Set errorMsg = "Input cannot be empty"
Return $$$ERROR($$$GeneralError, errorMsg)
}
Set result = $ZCONVERT(input, "U")
Return $$$OK
}
Referencias de Documentación
4. Pasa objetos a métodos (paso de oref)
Puntos Clave
- Las referencias de objeto (orefs) se pasan por valor por defecto, pero el oref es un puntero al objeto
- Modificar las propiedades de un objeto pasado afecta al objeto original (referencia compartida)
- Asignar un nuevo objeto a la variable del parámetro NO afecta la variable del llamador
- La verificación de tipos se realiza en tiempo de compilación cuando se especifican los tipos de argumentos
- Los objetos tienen conteo de referencias; persisten mientras al menos una variable los referencie
Notas Detalladas
Descripción general
Cuando pasa un objeto a un método, está pasando la referencia de objeto (oref), que es esencialmente un puntero al objeto en memoria. Comprender esto es crítico para evitar errores relacionados con modificaciones no intencionadas o referencias perdidas.
Paso de Objetos
Class Sample.OrderProcessor Extends %RegisteredObject
{
ClassMethod ApplyDiscount(order As Sample.Order, pct As %Numeric)
{
// This modifies the ORIGINAL order object
Set order.Total = order.Total * (1 - (pct / 100))
}
ClassMethod ProcessOrder(order As Sample.Order) As %Status
{
// Validate the order
If order.Total <= 0 {
Return $$$ERROR($$$GeneralError, "Invalid total")
}
// Modify the order's status
Set order.Status = "Processed"
Return order.%Save()
}
}
Uso:
Set order = ##class(Sample.Order).%OpenId(1)
Write "Before: ", order.Total, ! // e.g., 100
Do ##class(Sample.OrderProcessor).ApplyDiscount(order, 10)
Write "After: ", order.Total, ! // 90 (original object modified)
Semántica de Valor de la Referencia
El oref en sí se pasa por valor. Reasignar la variable del parámetro dentro del método no cambia la variable del llamador:
ClassMethod ResetOrder(order As Sample.Order)
{
// This does NOT affect the caller's variable
Set order = ##class(Sample.Order).%New()
Set order.Total = 0
}
Set myOrder = ##class(Sample.Order).%OpenId(1)
Do ##class(Sample.OrderProcessor).ResetOrder(myOrder)
// myOrder still points to the original object (ID 1), unchanged
Para modificar realmente la variable del llamador, usar ByRef u Output:
ClassMethod ResetOrder(ByRef order As Sample.Order)
{
Set order = ##class(Sample.Order).%New()
Set order.Total = 0
}
// Now calling with: Do ##class(...).ResetOrder(.myOrder) changes myOrder
Paso de Objetos en Colecciones
ClassMethod ProcessAll(orders As %ListOfObjects) As %Status
{
For i = 1:1:orders.Count() {
Set order = orders.GetAt(i)
Set order.Status = "Processed"
}
Return $$$OK
}
Verificación del Tipo de Objeto en Tiempo de Ejecución
ClassMethod HandleItem(item As %RegisteredObject)
{
If item.%IsA("Sample.Order") {
// Order-specific logic
} ElseIf item.%IsA("Sample.Invoice") {
// Invoice-specific logic
}
}
Referencias de Documentación
5. Pasa variables por referencia (ByRef, sintaxis .variable en el sitio de llamada)
Puntos Clave
- El prefijo punto (.) en el sitio de llamada es el único mecanismo que controla el paso por referencia — es decisión del llamador
- `ByRef` en la firma del método es puramente indicativo (documentación) — no tiene efecto en tiempo de ejecución
- Sin el punto, el valor se pasa siempre por valor, independientemente de `ByRef` en la firma
- Con el punto, el valor se pasa siempre por referencia, incluso si la firma no tiene `ByRef`
- ByRef pasa el valor existente COMO ENTRADA y permite un nuevo valor COMO SALIDA
Notas Detalladas
Descripción general
Por defecto, ObjectScript pasa los argumentos por valor. Cuando un método necesita modificar una variable en el ámbito del llamador, el llamador debe pasar por referencia usando el prefijo punto (.). La palabra clave ByRef en la firma es una mejor práctica para documentación pero no tiene efecto de aplicación — es enteramente responsabilidad del llamador usar el punto.
Patrón Básico de ByRef
ClassMethod Swap(ByRef a As %String, ByRef b As %String)
{
Set temp = a
Set a = b
Set b = temp
}
Llamando:
Set x = "Hello"
Set y = "World"
Do ##class(Sample.Util).Swap(.x, .y)
Write x // "World"
Write y // "Hello"
Olvidar el Punto
Un error común es olvidar el punto en el sitio de llamada:
Set x = "Hello"
Set y = "World"
Do ##class(Sample.Util).Swap(x, y) // NO dots - passed by value!
Write x // Still "Hello" - unchanged
Write y // Still "World" - unchanged
El método se ejecuta sin error, pero las variables del llamador no se modifican porque se pasaron copias.
Output vs ByRef Revisitado
Con Output, el valor inicial de la variable no se pasa al método:
ClassMethod GetInfo(Output name As %String, Output count As %Integer)
{
Set name = "Test"
Set count = 42
}
// Calling:
Do ##class(Sample.Util).GetInfo(.n, .c)
Write n // "Test"
Write c // 42
Con ByRef, el valor existente SÍ está disponible dentro del método:
ClassMethod AppendSuffix(ByRef text As %String, suffix As %String)
{
Set text = text _ suffix
}
Set myText = "Hello"
Do ##class(Sample.Util).AppendSuffix(.myText, " World")
Write myText // "Hello World"
Ejemplo Práctico: Recolección de Errores
ClassMethod ValidateRecord(record As Sample.Record, ByRef errors As %List) As %Boolean
{
// errors may already contain items from prior validation
If record.Name = "" {
Set errors = errors _ $LB("Name is required")
}
If record.Age < 0 {
Set errors = errors _ $LB("Age must be positive")
}
Return ($LISTLENGTH(errors) = 0)
}
Referencias de Documentación
6. Pasa variables multidimensionales por referencia (paso de arrays)
Puntos Clave
- ObjectScript soporta variables multidimensionales (arrays con subíndices)
- Pasar arrays por referencia usando el prefijo punto (.) para compartir todo el árbol de subíndices
- El método recibe el array con todos sus subíndices intactos
- Usar $ORDER para iterar sobre los subíndices
- Los arrays no pueden pasarse por valor (solo se copiaría el nodo superior sin los subíndices)
Notas Detalladas
Descripción general
Las variables multidimensionales (arrays) son una estructura de datos fundamental en ObjectScript. Almacenan datos en múltiples niveles de subíndices dentro de un solo nombre de variable. Pasar arrays a métodos requiere paso por referencia para incluir todos los niveles de subíndices.
Fundamentos de Variables Multidimensionales
Set colors("red") = "#FF0000"
Set colors("green") = "#00FF00"
Set colors("blue") = "#0000FF"
Set colors("blue", "light") = "#ADD8E6"
Set colors("blue", "dark") = "#00008B"
Paso de Arrays a Métodos
ClassMethod DisplayColors(ByRef colors)
{
Set key = ""
For {
Set key = $ORDER(colors(key))
Quit:key=""
Write key, ": ", colors(key), !
}
}
Llamando:
Set colors("red") = "#FF0000"
Set colors("green") = "#00FF00"
Set colors("blue") = "#0000FF"
Do ##class(Sample.Util).DisplayColors(.colors)
Salida:
blue: #0000FF
green: #00FF00
red: #FF0000
Construcción de Arrays Dentro de Métodos
ClassMethod GetStateCounts(Output states)
{
&sql(DECLARE C1 CURSOR FOR
SELECT State, COUNT(*) FROM Sample.Person GROUP BY State)
&sql(OPEN C1)
For {
&sql(FETCH C1 INTO :state, :cnt)
Quit:SQLCODE'=0
Set states(state) = cnt
}
&sql(CLOSE C1)
}
Llamando:
Do ##class(Sample.Util).GetStateCounts(.states)
Set st = "" For {
Set st = $ORDER(states(st)) Quit:st=""
Write st, ": ", states(st), !
}
Paso de Arrays Multi-Nivel
ClassMethod ProcessTree(ByRef tree, level As %Integer = 0)
{
Set key = ""
For {
Set key = $ORDER(tree(key))
Quit:key=""
Write ?level*4, key, ": ", $GET(tree(key)), !
// Recursively process sub-nodes
// Note: must merge to a temp variable for recursive call
Merge sub = tree(key)
If $DATA(sub) > 1 {
Do ..ProcessTree(.sub, level + 1)
}
Kill sub
}
}
Uso de $DATA para Verificar Nodos de Array
// $DATA returns:
// 0 - node doesn't exist
// 1 - node has data, no children
// 10 - node has children but no data
// 11 - node has both data and children
If $DATA(arr("key")) > 9 {
Write "Has child subscripts", !
}
Comando MERGE para Operaciones con Arrays
// Copy an entire array
Merge targetArr = sourceArr
// Copy a subtree
Merge targetArr = sourceArr("subtree")
Referencias de Documentación
7. Usa y sobrescribe métodos heredados (sobrescritura, llamada al padre)
Puntos Clave
- Las subclases heredan todos los métodos de su(s) superclase(s)
- Una subclase puede sobrescribir un método heredado definiendo un método con el mismo nombre
- El método que sobrescribe debe tener una firma compatible (mismos argumentos y tipo de retorno)
- La palabra clave Final previene que un método sea sobrescrito en subclases
- La sobrescritura es la base del polimorfismo en programación orientada a objetos
Notas Detalladas
Descripción general
La herencia de métodos permite que las subclases reutilicen el comportamiento de la clase padre. Cuando una subclase necesita un comportamiento diferente, sobrescribe el método heredado con su propia implementación. Este es un mecanismo clave de la programación orientada a objetos que habilita el polimorfismo.
Herencia Básica
Class Sample.Shape Extends %RegisteredObject
{
Property Color As %String;
Method Describe() As %String
{
Return "A shape of color " _ ..Color
}
Method Area() As %Numeric
{
Return 0
}
}
Una subclase hereda todos los métodos automáticamente:
Class Sample.Circle Extends Sample.Shape
{
Property Radius As %Numeric;
/// Override Area to compute circle area
Method Area() As %Numeric
{
Return $ZPI * (..Radius ** 2)
}
/// Override Describe
Method Describe() As %String
{
Return "A circle of radius " _ ..Radius _ " and color " _ ..Color
}
}
Comportamiento Polimórfico
ClassMethod PrintShapeInfo(shape As Sample.Shape)
{
// Calls the appropriate version based on actual object type
Write shape.Describe(), !
Write "Area: ", shape.Area(), !
}
// Works with any Shape subclass
Set c = ##class(Sample.Circle).%New()
Set c.Radius = 5
Set c.Color = "Red"
Do ##class(Sample.Util).PrintShapeInfo(c)
// Output: A circle of radius 5 and color Red
// Area: 78.5398...
La Palabra Clave Final
Marcar un método como Final previene que las subclases lo sobrescriban:
Class Sample.Base Extends %RegisteredObject
{
/// This method cannot be overridden
Method Validate() As %Status [ Final ]
{
// Validation logic that must not be changed
Return $$$OK
}
}
Intentar sobrescribir un método Final en una subclase causa un error de compilación.
Reglas de Sobrescritura
- El método que sobrescribe debe tener los mismos tipos de argumentos y tipo de retorno
- Un método de instancia solo puede sobrescribirse por un método de instancia (igual para ClassMethod)
- Si el método padre es Final, no puede sobrescribirse
- El método que sobrescribe puede llamar a la implementación padre usando
##super()
Referencias de Documentación
8. Determina cuándo usar ##super para llamar métodos de la superclase
Puntos Clave
- ##super() llama a la implementación de la superclase del método actual
- Usar ##super cuando se desea extender el comportamiento padre, no reemplazarlo completamente
- Patrón común: llamar a ##super primero para inicialización, luego agregar lógica personalizada
- ##super sigue la cadena de herencia (llama a la siguiente clase en el MRO)
- Crítico en %OnNew(), %OnOpen(), %OnValidateObject() y otros métodos callback
Notas Detalladas
Descripción general
Al sobrescribir un método, a menudo se desea mantener el comportamiento del padre y agregarlo en lugar de reemplazarlo completamente. La macro ##super() llama a la versión del método de la clase padre. Esto es especialmente importante en métodos callback donde la clase padre realiza configuración esencial.
Uso Básico de ##super
Class Sample.Employee Extends Sample.Person
{
Property Department As %String;
Method Describe() As %String
{
// Get the parent description first
Set desc = ##super()
// Extend it with employee-specific info
Return desc _ " (Dept: " _ ..Department _ ")"
}
}
##super en Métodos Callback
Los métodos callback como %OnNew(), %OnValidateObject() y %OnAfterSave() están definidos en clases del sistema. Cuando los sobrescribe, típicamente debe llamar a ##super() para asegurar que el comportamiento del sistema se preserve:
Class Sample.AuditedRecord Extends %Persistent
{
Property CreatedBy As %String;
Property CreatedDate As %Date;
Property ModifiedDate As %Date;
Method %OnNew(initvalue As %String) As %Status
{
// Call parent's %OnNew first
Set sc = ##super(initvalue)
If $$$ISERR(sc) Return sc
// Add custom initialization
Set ..CreatedBy = $USERNAME
Set ..CreatedDate = +$HOROLOG
Set ..ModifiedDate = +$HOROLOG
Return $$$OK
}
Method %OnBeforeSave(insert As %Boolean) As %Status
{
Set sc = ##super(insert)
If $$$ISERR(sc) Return sc
// Update modified date on every save
Set ..ModifiedDate = +$HOROLOG
Return $$$OK
}
}
Cuándo Usar ##super
| Escenario | Usar ##super? | Razón |
|---|---|---|
| Extender el comportamiento padre | Sí | Preservar la lógica padre, agregar la propia |
| Reemplazar completamente el comportamiento | No | La lógica padre no se necesita |
| Métodos callback (%OnNew, etc.) | Generalmente sí | El padre puede realizar configuración esencial |
| Sobrescritura de método abstracto | No | El padre no tiene implementación |
| Herencia múltiple | Sí (con cuidado) | ##super sigue la cadena MRO |
##super con Argumentos
Pasar los mismos argumentos al padre:
Method Process(data As %String, options As %String = "") As %Status
{
// Pre-processing
Set data = $ZSTRIP(data, "<>W")
// Call parent with the modified data
Set sc = ##super(data, options)
If $$$ISERR(sc) Return sc
// Post-processing
Do ..LogActivity("Processed: " _ data)
Return $$$OK
}
##super en Herencia Múltiple
Con herencia múltiple, ##super() llama a la siguiente clase en el orden de resolución de métodos, no necesariamente al "padre" en un sentido de herencia simple:
Class MyApp.C Extends (MyApp.A, MyApp.B)
{
Method Init() As %Status
{
// Calls MyApp.A's Init (leftmost superclass)
Return ##super()
}
}
Error Común: Olvidar ##super
Olvidar llamar a ##super() en %OnNew() o %OnValidateObject() puede romper la inicialización o validación de la clase padre. Siempre considere si el padre tiene lógica que necesita preservar.
Referencias de Documentación
Resumen de Preparación para el Examen
Conceptos Críticos a Dominar:
- Los métodos de instancia usan la sintaxis `..`; los métodos de clase no pueden acceder a propiedades de instancia
- `..#ParameterName` funciona tanto en métodos de instancia como de clase
- Los parámetros se resuelven en tiempo de compilación y pueden sobrescribirse en subclases
- `Output` vs `ByRef`: Output no pasa el valor inicial como entrada; ByRef sí
- `ByRef` y `Output` en las firmas son puramente indicativos — el prefijo punto (.) del llamador es lo que realmente controla el paso por referencia
- Siempre usar el prefijo punto (.) en el sitio de llamada para parámetros ByRef y Output
- Los objetos pasados a métodos comparten la referencia; modificar propiedades afecta al original
- Reasignar la variable del parámetro no afecta al llamador a menos que se use ByRef
- Los arrays multidimensionales deben pasarse por referencia para incluir los subíndices
- `##super()` llama a la implementación padre; esencial en métodos callback
- Olvidar `##super()` en %OnNew o %OnValidateObject puede romper el comportamiento heredado
Escenarios Comunes en el Examen:
- Identificar si un método debe ser Method o ClassMethod
- Predecir la salida cuando una variable se pasa con o sin el prefijo punto
- Determinar qué valor de parámetro se usa cuando una subclase sobrescribe un parámetro
- Predecir el comportamiento cuando un objeto se pasa a un método y sus propiedades se modifican
- Decidir si debe llamarse ##super() en una sobrescritura de método
Recomendaciones de Práctica:
- Crear una jerarquía de clases con métodos de instancia y de clase; probar la sintaxis `..`
- Escribir métodos con parámetros ByRef y Output; probar con y sin el prefijo punto
- Pasar objetos a métodos y verificar que las modificaciones de propiedades son visibles para el llamador
- Construir e iterar sobre arrays multidimensionales pasados por referencia
- Sobrescribir métodos callback con y sin ##super() y observar las diferencias