There are two special methods, which are used to initialize a class and its objects.
The init
method is used to initialize a class, and in particular to initialize the values of any static variables. It is called automatically the first time that one of the class’s (static) fields is accessed, or when an instance of the class is created.
Some other points to note about init
:-
init
methods (if any) are called before the class’s.init
method is only ever called once.init
method must be declared as a private static
method.init
field via normal field access, so the method can only ever be invoked by the runtime system itself. There is however a library function, lang.Class.ensure_initialized()
which will ensure the given class’s init
method has been called, if it hasn’t been already.init
may not be called if a constant field access has been replaced by the value assigned to it in init
, during optimization. For example, we may have a class X
with a constant Y
, assigned the value 123
in X
’s init
method. Elsewhere in the program, the expression X.Y
would be replaced with 123
, by oit
’s optimizer. When encountered at runtime, 123
would not of course cause X
’s init
method to be run.const
fields can only be assigned to from within the init
method. In other words, you cannot call another method from init
and initialize constants there. This restriction is to help oit
in the constant folding process just described.The new
method is used to initialize an object, ie an instance of a particular class. The method is not invoked explicitly however. Rather, in order to create an instance the class name is used like a function call, and the new()
method is invoked automatically. So for example :-
import io
class X()
public new(a, b)
write("in new a=", a, " b=", b)
return
end
end
procedure main()
local i
i := X(3, 4)
end
This writes "in new a=3 b=4"
.
Some other points to note about new()
:-
new()
method. If it is absent, then all the instance variables are initially &null
.new()
method in a superclass, just like any other method.new()
method is respected. So making the new()
method private means that instances can only be created from within the class itself (by necessity in a static method).After an object has been initialized, the new()
method cannot be accessed, and any attempt to do so gives a run-time error. So in the example above, the following would not be allowed :-
procedure main()
local i
i := X(3, 4)
i.new(5, 6) # Runtime error
end
If the new()
method fails, then the creation of the object fails. This gives new()
extra control over the creation process, but does mean that you have to remember to put a return
in the new()
method somewhere.
It is sometimes desirable to provide a way of creating a new instance which bypasses the new()
method. The method lang.Class.create_instance()
provides a way to do this. It can be called from within a class, and it returns a new instance of that class. new()
is not invoked, and all of the instance variables are set to &null
. It is the responsibility of the caller to initialize the instance as appropriate.
Another method, lang.Class.create_raw_instance()
, is just like create_instance()
, except that the new object is in an even more primitive state, which allows const
fields to be assigned and new
to be invoked. The method lang.Class.complete_raw_instance()
must be used to complete the object’s initialization.
Here is an example illustrating the use of create_instance()
.
import io, lang
class X()
private x
public static f(x)
local i
write("In X.f()")
i := Class.create_instance()
i.x := 2 * x
return i
end
public new(x)
write("In X.new()")
self.x := 3 * x
return
end
end
procedure main()
write(to_string(X(123)))
write(to_string(X.f(345)))
end
The output is :-
In X.new()
object X#1(x=369)
In X.f()
object X#2(x=690)
Contents