Page 1 of 1

Referencing another class in a class constructor

Posted: Mon Jul 01, 2019 1:44 am
by mfleming
As part of a class constructor I would like to create an instance of another class and assign it to a field within the class instance I'm creating. Even if the two classes are in the same namespace, I get an undefined name value error for the code

Code: Select all

∇new0
:Access Public
:Implements Constructor
matl← ⎕NEW Material



In this example I have a namespace RayTracer and two classes within it, Shape and Material. The use of :Include with the enclosing namespace reference doesn't help, nor unfortunately does ⎕PATH. If I use an absolute path reference to Material, all is fine but it is not what I would prefer. A local relative path reference works, but only if I'm within the enclosing RayTracer namespace, i.e.

Code: Select all

matl← ⎕NEW ##.Material


If I try to create the class instance outside of the enclosing RayTracer namespace, for example in #, that also fails with undefined name. What I need is the equivalent of ⎕PATH for class references. Having to code all references as absolute within a constructor would pin me to a particular place, as in

Code: Select all

matl← ⎕NEW #.RayTracer.Material


The only alternative at the moment is to not assign the field in the constructor at all, but assign a class instance after creation like this

Code: Select all

⍝ Within RayTracer namespace
p←⎕NEW Shape
p.matl←⎕NEW Material

⍝ or anywhere else
p←⎕NEW #.RayTracer.Shape
p.matl←⎕NEW #.RayTracer.Material


This will work regardless of where I am, but requires a little extra work on the part of the programmer. Any suggestions on avoiding full namespace path references within the class code I'm writing if I'd like to create instances of other classes within constructors?

Thanks in advance,
~Mark

Re: Referencing another class in a class constructor

Posted: Mon Jul 01, 2019 11:13 am
by paulmansour
I if remember correctly, the problem here may be the naked ⎕NEW, which creates an instance of a class where the ⎕NEW is called, thus leaving the instance with no knowledge of where the actual class definition is (or where its brother and sister classes are).

I always ask the class to create its own instance using a static .New method. This ensures that all instances of the class are in a predictable location, and can thus find all related class definitions (or any other related assets) via relative paths by going up and over using ##. Something like:

Code: Select all

z←New x                      ⍝ Creates a New Instance
 :Access Public Shared        ⍝
 z←##.⎕NEW(↑∊⎕CLASS ⎕THIS)x   ⍝