Skip to main content

Classes

This page discusses the basic rules for defining and working with classes in InterSystems IRIS®.

Classes discusses objects and object classes.

Class Names and Packages

Each InterSystems IRIS class has a name, which must be unique within the namespace where it is defined. A full class name is a string delimited by one or more periods, as in the following example: package.subpackage.subpackage.class. The short class name is the part after the final period within this string; the part preceding the final period is the package name.

The package name is simply a string, but if it contains periods, the InterSystems IRIS development tools treat each period-delimited piece as a subpackage. Your Integrated Development Environment (IDE) and other tools display these subpackages as a hierarchy of folders, for convenience.

Basic Contents of a Class Definition

An InterSystems IRIS class definition can include the following items, all known as class members:

  • Methods — There are two kinds of methods: instance methods and class methods (called static methods in other languages). In most cases, a method is a subroutine.

  • Parameters — A parameter defines a constant value for use by this class. The value is set at compilation time.

  • Properties — A property contains data for an instance of the class.

  • Class queries — A class query defines an SQL query that can be used by the class and specifies a class to use as a container for the query.

  • XData blocks — An XData block is a well-formed XML document within the class, for use by the class.

  • Other kinds of class members that are relevant only for persistent classes.

InterSystems IRIS class definitions use Class Definition Language (CDL) to specify the class and its members. You can use either Python or ObjectScript to write the executable code inside of methods.

A class definition can include keywords; these affect the behavior of the class compiler. You can specify some keywords for the entire class, and others for specific class members. These keywords affect the code that the class compiler generates and thus control the behavior of the class.

The following shows a simple InterSystems IRIS class definition with methods written in ObjectScript and in Python:

Class MyApp.Main.SampleClass Extends %RegisteredObject
{

Parameter CONSTANTMESSAGE [Internal] = "Hello world!" ;

Property VariableMessage As %String [ InitialExpression = "How are you?"];

Property MessageCount As %Numeric [Required];

ClassMethod HelloWorld() As %String [ Language = objectscript ]
 {
    Set x=..#CONSTANTMESSAGE
    Return x
 }

Method WriteIt() [ Language = objectscript, ServerOnly = 1]
{
    Set count=..MessageCount
    For i=1:1:count {
        Write !,..#CONSTANTMESSAGE," ",..VariableMessage
        }
    }

}
Class MyApp.Main.SampleClass Extends %RegisteredObject
{

Parameter CONSTANTMESSAGE [Internal] = "Hello world!" ;

Property VariableMessage As %String [ InitialExpression = "How are you?"];

Property MessageCount As %Numeric [Required];

ClassMethod MessageWrapper() As %String [ Language = objectscript ]
{
     return ..#CONSTANTMESSAGE
}

ClassMethod HelloWorld() As %String [ Language = python ]
 {
    import iris
    x = iris.cls("MyApp.Main.SampleClass").MessageWrapper()
    return x
 }

Method WriteIt() [ ServerOnly = 1, Language = python ]
{
    import iris
    CONSTANTMESSAGE = self.MessageWrapper()
    count = self.MessageCount
    print()
    for i in range(count):
        print(CONSTANTMESSAGE, self.VariableMessage)
}

}

Note the following points:

  • The first line gives the name of the class. MyApp.Main.SampleClass is the full class name, MyApp.Main is the package name, and SampleClass is the short class name.

    Your IDE and other user interfaces treat each package as a folder.

  • Extends is a compiler keyword.

    The Extends keyword specifies that this class is a subclass of %RegisteredObjectOpens in a new tab, which is a system class provided for object support. This example class extends only one class, but it is possible to extend multiple other classes. Those classes, in turn, can extend other classes.

  • CONSTANTMESSAGE is a parameter. By convention, all parameters in InterSystems IRIS system classes have names in all capitals. This is a convenient convention, but you are not required to follow it.

    The Internal keyword is a compiler keyword. It marks this parameter as internal, which suppresses it from display in the class documentation. This parameter has a string value.

    You must access class parameters via ObjectScript. In the Python version of this class, we use the ObjectScript class method MessageWrapper() to return the value of the parameter.

  • You can access any class method from Python. You can use the iris.cls("Package.Class").classMethodName() syntax in all contexts, and the self.classMethodName() syntax from within a Python instance method. The example shows both syntax forms.

  • VariableMessage and MessageCount are properties. The item after As indicates the types for these properties. InitialExpression and Required are compiler keywords.

    You can access an InterSystems IRIS class property directly from ObjectScript or Python, as in the example.

  • HelloWorld() is a class method and it returns a string; this is indicated by the item after As.

    This method uses the value of the class parameter.

  • WriteIt() is an instance method and it does not return a value.

    This method uses the value of the class parameter and values of two properties.

    The ServerOnly compiler keyword means that this method will not be projected to external clients.

The following Terminal session shows how we can use this class. Both terminal shells are valid for the ObjectScript and Python versions of the class.

TESTNAMESPACE>write ##class(MyApp.Main.SampleClass).HelloWorld()
Hello world!
TESTNAMESPACE>set x=##class(MyApp.Main.SampleClass).%New()
 
TESTNAMESPACE>set x.MessageCount=3
 
TESTNAMESPACE>do x.WriteIt()
 
Hello world! How are you?
Hello world! How are you?
Hello world! How are you?
>>> print(iris.cls("MyApp.Main.SampleClass").HelloWorld())
Hello world!
>>> x=iris.cls("MyApp.Main.SampleClass")._New()
>>> x.MessageCount=3
>>> x.WriteIt()

Hello world! How are you?
Hello world! How are you?
Hello world! How are you?

Shortcuts for Calling Class Methods

When calling class methods using ObjectScript, you can omit the package (or the higher level packages) in the following scenarios:

  • The reference is within a class, and the referenced class is in the same package or subpackage.

  • The reference is within a class, and the class uses the IMPORT directive to import the package or subpackage that contains the referenced class.

  • The reference is within a method, and the method uses the IMPORT directive to import the package or subpackage that contains the referenced class.

When calling class methods from ObjectScript or Python, you can omit the package (or higher level packages) in the following scenarios:

  • You are referring to a class in the %Library package, which is specially handled. You can refer to the class %Library.ClassName as %ClassName. For example, you can refer to %Library.StringOpens in a new tab as %StringOpens in a new tab.

  • You are referring to a class in the User package, which is specially handled. For example, you can refer to User.MyClass as MyClass.

    InterSystems does not provide any classes in the User package, which is reserved for your use.

In all other cases, you must always use the full package and class name to call a class method.

Class Parameters

A class parameter defines a value that is the same for all objects of a given class. With rare exceptions, this value is established when the class is compiled and cannot be altered at runtime. You use class parameters for the following purposes:

  • To define a value that cannot be changed at runtime.

  • To define user-specific information about a class definition. A class parameter is simply an arbitrary name-value pair; you can use it to store any information you like about a class.

  • To customize the behavior of the various data type classes (such as providing validation information) when used as properties; this is discussed in the next section.

  • To provide parameterized values for method generator methods to use.

You can define parameters in an InterSystems IRIS class that contains ObjectScript methods, Python methods, or a combination of the two. The following shows a class with several parameters:

Class GSOP.DivideWS Extends %SOAP.WebService
{

Parameter USECLASSNAMESPACES = 1;

///  Name of the Web service.
Parameter SERVICENAME = "Divide";

///  SOAP namespace for the Web service
Parameter NAMESPACE = "http://www.mynamespace.org";

/// let this Web service understand only SOAP 1.2
Parameter SOAPVERSION = "1.2";

 ///further details omitted
}
Note:

Class parameters can also be expressions, which can be evaluated either at compile time or runtime. For more information, see Defining and Referring to Class Parameters.

Properties

Formally, there are two kinds of properties in InterSystems IRIS:

  • Attributes, which hold values. The value can be any of the following:

    • A single, literal value, usually based on a data type.

    • An object value (this includes collection objects and stream objects).

    • A multidimensional array. This is less common.

    The word property often refers just to properties that are attributes, rather than properties that hold associations.

  • Relationships, which hold associations between objects.

You can define properties in a class containing ObjectScript methods, Python methods, or a combination of the two. However, you cannot access relationships from Python methods. This section shows a sample class that contains property definitions that show some of these variations:

Class MyApp.Main.Patient Extends %Persistent
{

Property PatientID As %String [Required];

Property Gender As %String(DISPLAYLIST = ",Female,Male", VALUELIST = ",F,M");

Property BirthDate As %Date;

Property Age As %Numeric [Transient];

Property MyTempArray [MultiDimensional];

Property PrimaryCarePhysician As Doctor;

Property Allergies As list Of PatientAllergy;

Relationship Diagnoses As PatientDiagnosis [ Cardinality = children, Inverse = Patient ]; 
}

Note the following:

  • In each definition, the item after As is the type of the property. Each type is a class. The syntax As List Of is shorthand for a specific collection class.

    %StringOpens in a new tab, %DateOpens in a new tab, and %NumericOpens in a new tab are data type classes.

    %StringOpens in a new tab is the default type.

  • Diagnoses is a relationship property; the rest are attribute properties.

  • PatientID, Gender, BirthDate, and Age can contain only simple, literal values.

  • PatientID is required because it uses the Required keyword. This means that you cannot save an object of this class if you do not specify a value for this property.

  • Age is not saved to disk, unlike the other literal properties. This is because it uses the Transient keyword.

  • MyTempArray is a multidimensional property because it uses the MultiDimensional keyword. This property is not saved to disk by default.

  • PrimaryCarePhysician and Allergies are object-valued properties.

  • The Gender property definition includes values for property parameters. These are parameters in the data type class that this property uses.

    This property is restricted to the values M and F. When you view the display values (as in the Management Portal), you see Male and Female instead. Each data type class provides methods such as LogicalToDisplay().

Specifying Property Keywords

In a property definition, you can include optional property keywords that affect how the property is used. The following list shows some of the most commonly seen keywords:

Specifies that the value of the property set before an instance of this class can be stored to disk. By default, properties are not required. In a subclass, you can mark an optional property as required, but you cannot do the reverse.

Specifies an initial value for the property. By default, properties have no initial value. Subclasses inherit the value of the InitialExpression keyword and can override it. The value specified must be a valid ObjectScript expression.

Specifies that the property is not stored in the database. By default, properties are not transient. Subclasses inherit the value of the Transient keyword and cannot override it.

Specifies that the property is private. Subclasses inherit the value of the Private keyword and cannot override it.

By default, properties are public and can be accessed anywhere. You can mark a property as private (via the Private keyword). If so, it can only be accessed by methods of the object to which it belongs.

In InterSystems IRIS, private properties are always inherited and visible to subclasses of the class that defines the property.

In other programming languages, these are often called protected properties.

Specifies that the property has no in-memory storage allocated for it when the object containing it is instantiated. By default, a property is not calculated. Subclasses inherit the Calculated keyword and cannot override it.

Specifies that the property is multidimensional. This property is different from other properties as follows:

  • It does not have associated methods (see the following topics).

  • It is ignored when the object is validated or saved.

  • It is not saved to disk, unless your application includes code to save it specifically.

  • It cannot be exposed to client technologies.

  • It cannot be stored in or exposed through SQL tables.

Multidimensional properties are rare but are occasionally useful to temporarily contain object state information.

Properties Based on Data Types

When you define a property and you specify its type as a data type class, you have special options for defining and working with that property, as described in this section.

Data Type Classes

Data type classes enable you to enforce sets of rules about the values of properties.

InterSystems IRIS provides data type classes which include %Library.StringOpens in a new tab, %Library.IntegerOpens in a new tab, %Library.NumericOpens in a new tab, %Library.DateOpens in a new tab, and many others. Because the names of classes of the %Library package can be abbreviated, you can abbreviate many of these; for example, %DateOpens in a new tab is an abbreviation for %Library.DateOpens in a new tab.

Each data type class has the following features:

  • It specifies values for compiler keywords. For a property, a compiler keyword can do things like the following:

    • Make the property required

    • Specify an initial value for the property

    • Control how the property is projected to SQL, ODBC, and Java clients

  • It specifies values for parameters that affect the details such as the following:

    • Maximum and minimum allowed logical value for the data type

    • Maximum and minimum number of characters the string can contain

    • Number of digits following the decimal point

    • Whether to truncate the string if it exceeds the maximum number of characters

    • Display format

    • How to escape any special XML or HTML characters

    • Enumerated lists of logical values and display values to use in any user interface

    • Pattern that the string must match (automatically uses the InterSystems IRIS pattern-matching operator)

    • Whether to respect or ignore the UTC time zone when importing or exporting to XML

  • It provides a set of methods to translate literal data among the stored (on disk), logical (in memory), and display formats.

You can add your own data type classes. For example, the following shows a custom subclass of %Library.StringOpens in a new tab:

Class MyApp.MyType Extends %Library.String
{

/// The maximum number of characters the string can contain.
Parameter MAXLEN As INTEGER = 2000;

}

Overriding Parameters of Data Type Classes

When you define a property and you specify its type as a data type class, you can override any parameters defined by the data type class.

For example, the %IntegerOpens in a new tab data type class defines the class parameter (MAXVAL) but provides no value for this parameter. You can override this in a property definition as follows:

Property MyInteger As %Integer(MAXVAL=10);

For this property, the maximum allowed value is 10.

(Internally, this works because the validation methods for the data type classes are method generators; the parameter value you provide is used when the compiler generates code for your class.

Similarly, every property of type %StringOpens in a new tab has a collation type, which determines how values are ordered (such as whether capitalization has effects or not). The default collation type is SQLUPPER.

For another example, the data type classes define the DISPLAYLIST and VALUELIST parameters, which you can use to specify choices to display in a user interface and their corresponding internal values:

Property Gender As %String(DISPLAYLIST = ",Female,Male", VALUELIST = ",F,M");

Using Other Property Methods

Properties have a number of methods associated with them automatically. These methods are generated by the data type classes and can be accessed from ObjectScript.

For example, if we define a class Person with three properties:

Class MyApp.Person Extends %Persistent
{
Property Name As %String;
Property Age As %Integer;
Property DOB As %Date;
}

The name of each generated method is the property name concatenated with the name of the method from the inherited class. You can access these generated methods from ObjectScript, as in the example below. You can access the same information from Python by calling the associated method directly from the inherited class. For example, some of the methods associated with the %DateOpens in a new tab class and therefore the DOB property are:

 Set x = person.DOBIsValid(person.DOB)
 Write person.DOBLogicalToDisplay(person.DOB)
x = iris.cls("%Date").IsValid(person.DOB)
print(iris.cls("%Date").LogicalToDisplay(person.DOB))

where IsValid is a method of the property class and LogicalToDisplay is a method of the %DateOpens in a new tab data type class.

Methods

There are two kinds of methods: instance methods and class methods (called static methods in other languages).

Specifying Method Keywords

In a method definition, you can include optional compiler keywords that affect how the method behaves. The following list shows some of the most commonly seen method keywords:

In InterSystems IRIS, methods can be written in ObjectScript or Python. To specify which language you will write a method in, use the following syntax:

Method MyMethod() [ Language = objectscript ]
{
    // implementation details written in ObjectScript
}
Method MyMethod() [ Language = python ]
{
    # implementation details written in Python
}

If a method does not use the Language keyword the compiler will assume that the method is written in ObjectScript.

You must write the method’s language in all lowercase letters, as in the example.

This keyword specifies that the method is private and can only be used with ObjectScript methods. Subclasses inherit the value of the Private keyword and cannot override it.

By default, methods are public and can be accessed anywhere. You can mark a method as private (via the Private keyword). If you do:

  • It can only be accessed by methods of the class to which it belongs.

  • It does not appear in the InterSystems Class Reference.

It is, however, inherited and available in subclasses of the class that defines the method.

Other languages often call such methods protected methods.

References to Other Class Members

Within a method, use the syntax shown here to refer to other class members:

  • To refer to a parameter in ObjectScript, use an expression like this:

     ..#PARAMETERNAME

    You can only access a parameter directly using ObjectScript. To access a parameter from Python, use an ObjectScript wrapper method to return the parameter and call this method when needed. For example:

    Class User.Employee Extends %RegisteredObject
    {
    
    Parameter ADDRESS = "123 Main St.";
    
    ClassMethod AddressWrapper() As %String [ Language = objectscript ]
    {
        return ..#ADDRESS
    }
    
    ClassMethod OfficeLocation() [ Language = python ]
    {
        import iris
        location=iris.cls("User.Employee").AddressWrapper()
        print("This office is located at", location)
    }
    
    Method EmployeeLocation() [ Language = python ]
    {
        location=self.AddressWrapper()
        print("This employee works at", location)
    }
    
    }

    To access a class method from Python you can use the iris.cls("Package.Class").classMethodName() syntax in all contexts. From within a Python instance method, you can also use the shorter self.classMethodName() syntax.

    In classes provided by InterSystems, all parameters are defined in all capitals, by convention, but your code is not required to do this.

  • To refer to another instance method, use an expression like this:

     ..methodname(arguments)
    self.methodname(arguments)

    Note that you cannot use this syntax within a class method to refer to an instance method.

  • To refer to another class method, use the following syntax:

     ..classmethodname(arguments)
    iris.cls("Package.Class").classmethodname(arguments)

    Note that you cannot use the Python self syntax to access a class method.

  • (Within an instance method only) To refer to a property of the instance, use an expression like this:

     ..PropertyName
    self.PropertyName
    

    Similarly, to refer to a property of an object-valued property, use an expression like this:

     ..PropertyNameA.PropertyNameB
    self.PropertyNameA.PropertyNameB

    The syntax used in the ObjectScript examples is known as InterSystems IRIS dot syntax.

    Also, you can invoke an instance method or class method of an object-valued property. For example:

     Do ..PropertyName.MyMethod()
    self.PropertyName.MyMethod()

References to Methods of Other Classes

Within a method (or within a routine), use the syntax shown here to refer to a method in some other class:

  • To invoke a class method and access its return value, use an expression like the following:

     ##class(Package.Class).MethodName(arguments)
    iris.cls("Package.Class").MethodName(arguments)
    

    For example:

     Set x=##class(Util.Utils).GetToday()
    x=iris.cls("Util.Utils").GetToday()

    You can also invoke a class method without accessing its return value as follows:

     Do ##class(Util.Utils).DumpValues()
    iris.cls("Util.Utils").DumpValues()
    Note:

    ##class is not case-sensitive.

  • To invoke an instance method, create an instance and then use an expression like the following in either ObjectScript or Python to invoke the method and access its return value:

    instance.MethodName(arguments)

    For example:

     Set x=instance.GetName()
    x=instance.GetName()

    You can also invoke an instance method without accessing its return value by calling the method as follows:

     Do instance.InsertItem("abc")
    instance.InsertItem("abc")

Not all methods have return values, so choose the syntax appropriate for your case.

References to Current Instance

Within an instance method, sometimes it is necessary to refer to the current instance itself, rather than to a property or method of the instance. For example, you might need to pass the current instance as an argument when invoking some other code.

In ObjectScript, use the special variable $THIS to refer to the current instance. In Python, use the variable self to refer to the current instance.

For example:

 Set sc=header.ProcessService($this)
sc=header.ProcessService(self)

Method Arguments

A method can take positional arguments in a comma-separated list. For each argument, you can specify a type and the default value.

For instance, here is the partial definition of a method that takes three arguments. This is valid syntax for both ObjectScript and Python methods within InterSystems IRIS classes:

Method Calculate(count As %Integer, name, state As %String = "CA") as %Numeric
{
    // ...
}

Notice that two of the arguments have explicit types, and one has an default value. Generally it is a good idea to explicitly specify the type of each argument.

Note:

If a method is defined in Python and has any arguments with default values, then these arguments must be at the end of the argument list to avoid a compilation error.

Skipping Arguments

When invoking a method you can skip arguments if there are suitable defaults for them. ObjectScript and Python each have their own syntax to skip arguments.

In ObjectScript, you can skip over an argument by providing no value for that argument and maintaining the comma structure. For example, the following is valid:

 set myval=##class(mypackage.myclass).GetValue(,,,,,,4)

In an InterSystems IRIS class, a Python method’s signature must list the required arguments first, followed by any arguments with default values.

When calling the method, you must provide arguments in the order of the method’s signature. Therefore, once you skip an argument you must also skip all arguments following it. For example, the following is valid:

ClassMethod Skip(a1, a2 As %Integer = 2, a3 As %Integer = 3) [ Language = python ]
{
    print(a1, a2, a3)
}
TESTNAMESPACE>do ##class(mypackage.myclass).Skip(1)
1 2 3

Passing Variables by Value or by Reference

When you invoke a method, you can pass values of variables to that method either by value or by reference.

The signature of a method usually indicates whether you are intending to pass arguments by reference. For example:

Method MyMethod(argument1, ByRef argument2, Output argument3)

The ByRef keyword indicates that you should pass this argument by reference. The Output keyword indicates that you should pass this argument by reference and that the method ignores any value that you initially give to this argument.

Similarly, when you define a method, you use the ByRef and Output keywords in the method signature to inform other users of the method how it is meant to be used.

To pass an argument by reference in ObjectScript, place a period before the variable name when invoking the method. In Python, use iris.ref() on the value you want to pass and call the method on the reference. Both of these are shown in the following example:

 Do MyMethod(arg1, .arg2, .arg3)
arg2=iris.ref("peanut butter")
arg3=iris.ref("jelly")
MyMethod(arg1,arg2,arg3)
Important:

The ByRef and Output keywords provide information for the benefit of anyone using the InterSystems Class Reference. They do not affect the behavior of the code. It is the responsibility of the writer of the method to enforce any rules about how the method is to be invoked.

Variable Numbers of Arguments

You can define a method so that it accepts a variable number of arguments. For example:

ClassMethod MultiArg(Arg1... As %List) [ Language = objectscript ]
{
 Set args = $GET(Arg1, 0)
 Write "Invocation has ",
     args,
     " element",
     $SELECT((args=1):"", 1:"s"), !
 For i = 1 : 1 : args
 {
     Write "Argument[", i , "]: ", $GET(Arg1(i), "<NULL>"), !
 }
}
ClassMethod MultiArg(Arg1... As %List) [ Language = Python ]
{
    print("Invocation has", len(Arg1), "elements")
    for i in range(len(Arg1)):
        print("Argument[" + str(i+1) + "]: " + Arg1[i])
}

Specifying Default Values

To specify an argument’s default value in either an ObjectScript or a Python method, use the syntax as shown in the following example:

Method Test(flag As %Integer = 0)
{
 //method details
}

When a method is invoked, it uses its default values (if specified) for any missing arguments. If a method is written in Python, then any arguments with default values must be defined at the end of the argument list.

In ObjectScript, another option is to use the $GET function to set a default value. For example:

Method Test(flag As %Integer)
{
  set flag=$GET(flag,0)
 //method details
}

This technique, however, does not affect the class signature.

Method Generators

A method generator is a program that is invoked by the class compiler during class compilation. Its output is the actual runtime implementation of the method. Method generators provide a means of inheriting methods that can produce high performance, specialized code that is customized to the needs of the inheriting class or property. Within the InterSystems IRIS library, method generators are used extensively by the data type and storage classes.

Class Queries

An InterSystems IRIS class can contain class queries. A class query defines an SQL query that can be used by the class and specifies a class to use as a container for the query. The following shows an example:

Query QueryName(Parameter As %String) As %SQLQuery
{
SELECT MyProperty, MyOtherProperty FROM MyClass
 WHERE (MyProperty = "Hello" AND MyOtherProperty = :Parameter)
 ORDER BY MyProperty
}

You define class queries to provide predefined lookups for use in your application. For example, you can look up instances by some property, such as by name, or provide a list of instances that meet a particular set of conditions, such as all the flights from Paris to Madrid. The example shown here uses a parameter, which is a common way to provide a flexible query. Note that you can define class queries within any class; there is no requirement to include class queries within persistent classes, which are introduced later in this book.

XData Blocks

Because XML is often a useful way to represent structured data, InterSystems IRIS classes include a mechanism that allow you to include well-formed XML documents, for any need you might have. To do this, you include an XData block, which is another kind of class member.

InterSystems IRIS uses XData blocks for certain specific purposes, and these might give you ideas for your own applications:

  • WS-Policy support for InterSystems IRIS web service services and web clients. See Creating Web Services and Web Clients. In this case, an XData block describes the security policy.

  • In Business Intelligence, you use XData blocks to define cubes, subject areas, KPIs, and other elements.

For more details, see Defining and Using XData Blocks.

Macros and Include Files in Class Definitions

In an InterSystems IRIS class definition, you can define macros in an ObjectScript method and use them in that method. More often, however, you define them in an include file, which you can include at the start of any class definition. For example:

Include (%assert, %callout, %occInclude, %occSAX)

/// Implements an interface to the XSLT Parser. XML contained in a file or binary
/// stream may be transformed
Class %XML.XSLT.Transformer Extends %RegisteredObject ...

Then any ObjectScript methods in that class can refer to any macros defined in that include file, or in its included include files.

Macros are inherited. That is, a subclass has access to all the same macros as its superclasses.

Inheritance Rules in InterSystems IRIS

As with other class-based languages, you can combine multiple class definitions via inheritance. An InterSystems IRIS class definition can extend (or inherit from) multiple other classes. Those classes, in turn, can extend other classes.

Note that InterSystems IRIS classes cannot inherit from classes defined in Python (meaning a class definition contained in a .py file) and vice versa.

The following subsections provide the basic rules for inheritance of classes in InterSystems IRIS.

Inheritance Order

InterSystems IRIS uses the following rules for inheritance order:

  1. By default, if a class member of a given name is defined in multiple superclasses, the subclass takes the definition from the left-most class in the superclass list.

  2. If the class definition contains Inheritance = right, then the subclass takes the definition from the right-most class in the superclass list.

    For reasons of history, most InterSystems IRIS classes contain Inheritance = right.

Primary Superclass

Any class that extends other classes has a single primary superclass.

No matter which inheritance order a class uses, the primary superclass is the first one, reading left to right.

For any class-level compiler keywords, a given class uses the values specified in its primary superclass.

For a persistent class, the primary superclass is especially important; see Classes and Extents.

Most-Specific Type Class

Although an object can be an instance belonging to the extents of more than one class — such as that of various superclasses — it always has a most-specific type class (MSTC). A class is the most specific type of an object when that object is an instance of that class, but is not an instance of any subclass of that class.

Overriding Methods

A class inherits methods (both class and instance methods) from its superclass or superclasses, which you can override. If you do so, you must ensure that the signature in your method definition matches the signature of the method you are overriding. Each argument of the subclass method must use the same data type as the superclass method's argument, or a subclass of that data type. The method in the subclass can, however, specify additional arguments that are not defined in the superclass.

You can override a method written in ObjectScript with a Python method and vice versa as long as the method signatures match.

Within a method in a subclass, you can refer to the method that it overrides in a superclass. To do so in ObjectScript, use the ##super() syntax. For example:

//overrides method inherited from a superclass
Method MyMethod() [ Language = objectscript ]
{
  //execute MyMethod as implemented in the superclass
  do ##super()
  //do more things....
}
Note:

##super is not case-sensitive.

For More Information

For more information on these topics, see the following resources:

  • Defining and Using Classes describes how to define classes and class members in InterSystems IRIS.

  • Class Definition Reference provides reference information for the compiler keywords that you use in class definitions.

  • The InterSystems Class Reference provides details on all non-internal classes provided with InterSystems IRIS.

FeedbackOpens in a new tab