Question
· Jun 27

Is it possible to create constructor overloads ?

I have a class that inherit from AbstractException

I would like to create a new constructor that has 5 parameters :

Class Foo Extends %Exception.AbstractException
{
    Method %OnNew(arg1 As %String, arg2 As %String, arg3 As %String, arg4 As %String, arg5 As %String) As %Status
    {
        quit ##super("some message")
    }
}

I cannot compile it : 

ERROR #5478: Keyword signature error in Foo:%OnNew, keyword 'method argument/s signature' must be '%Library.String,%Library.String,%Library.String,%Library.String,%Exception.AbstractException' or its subclass

It's possible to create a constructor that has 4 parameters (like AbstractException class) but no more.

AFAIK it's possible in other languages.

Product version: IRIS 2021.1
$ZV: IRIS for Windows (x86-64) 2021.1 (Build 215U) Wed Jun 9 2021 09:39:22 EDT
Discussion (6)4
Log in or sign up to continue

To my knowledge and (more importantly 😁) according to the documentation, it's not possible.

The types of the arguments in the subclass method must be consistent with the types of the arguments in the original method. Specifically, any given argument must be either the same as the original type or a subclass of the original type. 

The method in the subclass can have more arguments than the method in the superclass.

Note that in your case the problem is not the number of parameters/arguments, it's the type of the arguments that does not match the superclass %OnNew() (implemented in %Exception.AbstractException) arguments type:

Method %OnNew(pName As %String = "", pCode As %String = "", pLocation As %String = "", pData As %String = "", pInnerException As %Exception.AbstractException = {$$$NULLOREF}) As %Status [ Private ]

One option could be:

Class test.Foo Extends %Exception.AbstractException
{

Method %OnNew(arg1 As %String, arg2 As %String, arg3 As %String, arg4 As %String, pInnerException As %Exception.AbstractException = {$$$NULLOREF}, arg5 As %String) As %Status
{
        quit ##super("some message")
}

}

I like @Norman W. Freeman 's answer. That is the factory pattern and I use it regularly. %OnNew is a single method that is implemented in each class. There is a little known feature of %OnNew - it can return an oref whose type class is different from the class that implements %OnNew. In other words, %OnNew can be that factory method. Norman's Create() solution is cleaner IMO. The sole advantage (again, IMO) of a polymorphic %OnNew() is that it works with %New. I can provide a demo is anyone is interested.

The solution I found is to create a new static method that creates an instance and returns it : 

Class Foo Extends %Exception.AbstractException
{
    ClassMethod Create(arg1 As %String, arg2 As %String, arg3 As %String, arg4 As %String, arg5 As %String) As %Status
    {
        quit ..%New("some message")
    }
}

Before :

throw ##class(Foo).%New("args1", "args2", "args3", ...)

After : 

throw ##class(Foo).Create("args1", "args2", "args3", ...)

Actually, the problem is that %Exception.AbstractException already has five parameters. The error message you received is because the fifth argument has a type of %Exception.AbstractException and your fifth argument has a type of %String.

It is entirely possible to override the implementation of a member inherited from a super class so long as the inherited member is not defined as final and the signature of the local override is compatible with the inherited signature. The class compiler does perform a signature check to ensure the class does not violate the prime directive: Every instance of a class is implicitly a valid instance of its primary super class. Rewording that slightly - the interface of a class must be compatible with the interface of its primary super class. You can add new parameters to an inherited method but the existing parameters, those inherited, must declare a compatible type. A compatible type can be more specific (a subclass of the inherited type) but it cannot be a competely different type.

I tried adding a sixth parameter and also corrected the type of the fifth:

Class User.MyException Extends %Exception.AbstractException
{
 
Method %OnNew(pName As %String = "", pCode As %String = "", pLocation As %String = "", pData As %String = "", pInnerException As %Exception.AbstractException = {$$$NULLOREF}, myArg As %String) As %Status [ Private ]
{
}
 
}

This class compiled cleanly.

ObjectScript does not allow method overloading which is a different thing.