[go: up one dir, main page]

Menu

#2034 Sublassing Array does not seem to call subclass init method before checking arguments

5.2.0
open
nobody
None
none
5
2025-11-05
2025-10-11
No

Rexx version 5.1.0 64-bit on Linux Mint 21.3
As demonstrated by the following code:
The init method for the typedArray subclass is not called at all before the argumenmts for the superclass are checked.

Ruurd Idenburg

#!/usr/bin/env rexx
say
say "Rexx version:".RexxInfo~version "from:" .RexxInfo~date
say
say "Creating a typedDirectory subclass."
say
myDirectory = .typedDirectory~new('Rony')
say "This is a" myDirectory~class~id "instance"
say
say "Now trying to create a typedArray subclass."
say
myArray = .typedArray~new('Will')
say "This is a" myArray~class~id "instance"
exit

::class typedArray public subclass Array
::attribute type
/* instance 'init' Called with an invalid argument for the super class */
::method init
  say "Method 'init'' for typedArray instance"
  use strict arg type
  if "RTW"~pos(type[1]~upper)==0 
    then raise syntax 93.914 array(1,"R(ony),T(im),W(ill)",type)
/* superclass 'init' called with proper argument */
  self~init:super(1)
  self~type = type
exit

::class typedDirectory public subclass Directory
::attribute type
/* Called with an invalid argument for the super class */
::method init
  say "Method 'init' for typedDirectory instance"
  use strict arg type
  if "RTW"~pos(type[1]~upper)==0 
    then raise syntax 93.914 array(1,"R(ony),T(im),W(ill)",type)
/* superclass 'init' called with proper argument */
  self~init:super(1)
  self~type = type
exit 


Related

Bugs: #2034

Discussion

  • jfaucher

    jfaucher - 2025-10-11

    Seems to be the normal behavior... Even if not obvious at first sight.
    rexxref: Any object requiring initialization at creation time must define an INIT method. If this method is defined, the class object runs the INIT method after the object is created.

    myArray = .typedArray~new('Will')
    Here, the typedArrayclass doesn't have a new method.
    So the new method of Array is called.
    Implemented by the native method ArrayClass::newRexx.
    This method creates the array, using the argument 'Will' (error).
    Once the array is created, the init method is called, with ony one argument: the created array.

    // finish the class initialization and init calls.
    classThis->completeNewObject(temp);
    

    Here, classThis is your class typedArray.

    Possible solution: You could override the new method.
    This is the technique used by Rony for the TraceObject class.
    See CoreClasses.orx

    ::class "TraceObject" subclass StringTable public
    
    ---------------------- class level ----------------------
    ::method    activate    class
      expose option collector counter makeStringMethod notify
      self~activate:super
      option   ='N'         -- normal (makeString returns the TRACELINE entry)
      collector=.nil        -- no appending to the collector will take place
      makeStringMethod = .nil
      notify   =.nil        -- no appending to the notify object will take place
      counter  =0           -- value will be used to number the TraceObject instances
    
    ::method    new         class    -- a new instance gets requested
      expose option collector counter
      dt = .dateTime~new    -- take the current date and time
      forward class (super) continue -- let the superclass do the job
      newObj = result       -- fetch freshly created object
      newObj["TIMESTAMP"]=dt
      newObj["OPTION"]   =option
      counter += 1
      newObj["NUMBER"]   =counter
      if \collector~isNil then -- collector exists, append traceObject
         collector~append(newObj)
      return newObj         -- return the new object
    
     
  • Anonymous

    Anonymous - 2025-10-13

    Ok, thanks. I looked at the ooRexx C/C++ source code for supporting some classes NEW method and with my limited understanding of c(++) code I think the following is true:

    1. For .OBJECT subclasses with a NEW method without arguments all arguments are passed to the created subclass instance INIT method .
    2. For baseclasses that have a specified NEW method, the arguments for the base class are checked and reported as error if failed, and if accepted all following arguments are passed to the subclass instance INIT method
    3. For (all?) collections except .ARRAY a default size is used if none is specified on the NEW method and all (following) arguments are passed to the subclass instance INIT method.
    4. For .ARRAY it is possible to specify multiple arguments representing a multidimensional array and the NEW class method implementation checks that the arguments are numbers and if not yields the error message that is showed in the sample code above, and no instance is created

    5. Seems to me that for .ARRAY the first non-number argument and following arguments should be passed to the subclass instance INIT method, thus in the case of .SUBARRAY~new('TYPE') an default size array should be created and the TYPE argument should be passed to the instance INIT method. Or does that sound ridiculous and am I totally wrong?

      Ruurd Idenburg
     
  • Ruurd Idenburg

    Ruurd Idenburg - 2025-10-14

    I bypassed the problem by using a List instead of an Array, curious what the proper implementation is.

    Ruurd Idenburg

     
  • Ruurd Idenburg

    Ruurd Idenburg - 2025-10-30

    One more try to convince the behaviour is a (in my opinion serious) bug:

    #!/usr/bin/env rexx
    
    list = .myList~new("Mike")
    array = .myArray~new('Rick')
    
    ::class myList public subclass List
    ::method init
      say arg(1,A)
      self~init:super(10)
    
    ::class myArray public subclass Array
    ::method init
      say arg(1,A)
      self~init:super(10)
    

    If you run this code , you will notice that the init for myArray is not called at all, while it is the first class in the in the order of classes and it is not allowed to call the superclass init with the adapted argument(s).

    Would like some response on this matter. TIA

    Ruurd

     
    • jfaucher

      jfaucher - 2025-10-30

      I started a code review (attached file), which I stopped after you found a workaround. You will see that the Array class doesn't forward the 'new' arguments to 'init'.

      Several native classes respect what's written in rexxref.pdf 5.1.1.20. new:
      "If you specify args, new passes these arguments on the init message."
      Other classes don't, maybe for good reasons, but I can't tell.

      Update:

      Several classes (like 'List') don't check/use the arguments in the 'new' method.
      It's done in the init method:

       * The init method for this class.  This does delayed
       * initialization of this object until a INIT message is
       * received during initialization.
      

      That's why your test with myList is ok.

      OTH, 'Array' checks and uses the arguments in the 'new' method before sending the INIT message.
      If a delayed initialization was possible, then your test with myArray would be ok.
      But seems not possible because the array must be created with the requested size(s) passed by new.

              // allocate a new item
              Protected<ArrayClass> temp = new(totalSize) ArrayClass();
      

      Unless an array of the default size is created by newRexx, whatever the passed size(s), and an expensionArray is created from INIT?

          ArrayClass *expansionArray;         // actual array containing data (will be self-referential originall)
          RexxInternalObject *objects[1];     // the start of the array of stored objects.
      
       

      Last edit: jfaucher 2025-10-30
  • Ruurd Idenburg

    Ruurd Idenburg - 2025-10-30

    Well, the code shows that INIT is not called at all for the subclass instance. The subclass is responsible for calling the INIT for the superclass if necessary, via an INIT:SUPER call or via the FORWARD keyword . So I still think it should be fixed or the docs should be made more specific.

     
    • jfaucher

      jfaucher - 2025-10-31

      So I still think it should be fixed or the docs should be made more specific.

      I agree but I can't tell what is the preference of the ooRexx team.
      In the meantime, this code will work:

      ::class typedArray public subclass Array
      ::attribute type
      ::method new class
        say "Method 'new'' for typedArray instance"
        use strict arg type
        if "RTW"~pos(type[1]~upper)==0
          then raise syntax 93.914 array(1,"R(ony),T(im),W(ill)",type)
      /* superclass 'new' called with proper argument */
        self~new:super(1)
        myArray = result
        myArray~type = type
      exit myArray
      
       
      • Ruurd Idenburg

        Ruurd Idenburg - 2025-10-31

        Ok, thanks for your investigation, I'll wait and see.

        Ruurd

        On 10/31/25 10:06, jfaucher wrote:

        So I still think it should be fixed or the docs should be made
        more specific.
        

        I agree but I can't tell what is the preference of the ooRexx team.
        In the meantime, this code will work:

        |::classtypedArraypublicsubclassArray ::attributetype ::methodnewclass
        say"Method 'new'' for typedArray instance" usestrictargtype
        if"RTW"~pos(type[1]~upper)==0
        thenraisesyntax93.914array(1,"R(ony),T(im),W(ill)",type) / superclass
        'new' called with proper argument
        / self~new:super(1) myArray=result
        myArray~type=type exitmyArray |


        [bugs:#2034] https://sourceforge.net/p/oorexx/bugs/2034/ Sublassing
        Array does not seem to call subclass init method before checking
        arguments

        Status: open
        Group: 5.2.0
        Created: Sat Oct 11, 2025 11:34 AM UTC by Ruurd Idenburg
        Last Updated: Thu Oct 30, 2025 09:33 PM UTC
        Owner: nobody

        Rexx version 5.1.0 64-bit on Linux Mint 21.3
        As demonstrated by the following code:
        The init method for the typedArray subclass is not called at all
        before the argumenmts for the superclass are checked.

        Ruurd Idenburg

        !/usr/bin/env rexx

        say
        say "Rexx version:".RexxInfo~version "from:" .RexxInfo~date
        say
        say "Creating a typedDirectory subclass."
        say
        myDirectory = .typedDirectory~new('Rony')
        say "This is a" myDirectory~class~id "instance"
        say
        say "Now trying to create a typedArray subclass."
        say
        myArray = .typedArray~new('Will')
        say "This is a" myArray~class~id "instance"
        exit

        ::class typedArray public subclass Array
        ::attribute type
        / instance 'init' Called with an invalid argument for the super class /
        ::method init
        say "Method 'init'' for typedArray instance"
        use strict arg type
        if "RTW"~pos(type[1]~upper)==0
        then raise syntax 93.914 array(1,"R(ony),T(im),W(ill)",type)
        / superclass 'init' called with proper argument /
        self~init:super(1)
        self~type = type
        exit

        ::class typedDirectory public subclass Directory
        ::attribute type
        / Called with an invalid argument for the super class /
        ::method init
        say "Method 'init' for typedDirectory instance"
        use strict arg type
        if "RTW"~pos(type[1]~upper)==0
        then raise syntax 93.914 array(1,"R(ony),T(im),W(ill)",type)
        / superclass 'init' called with proper argument /
        self~init:super(1)
        self~type = type
        exit


        Sent from sourceforge.net because you indicated interest in <https: sourceforge.net="" p="" oorexx="" bugs="" 2034=""></https:>

        To unsubscribe from further messages, please visit <https: sourceforge.net="" auth="" subscriptions=""></https:>

         

        Related

        Bugs: #2034

  • Rony G. Flatscher

    Hi Ruurd,

    if you study the Array class in the reference you will see that it defines its own NEW class method. Therefore you need to study it to see what it does. As you will see Array's NEW method does not send an INIT message to a newly created Array object.

    This is different than the behaviour of Object's NEW class method which will send the newly created object the INIT message with the received arguments in the same order, if any.

    If you want to take care of creating Array objects in a different way than Array's NEW class method you need to implement your own version of a NEW class method in your subclass.

    HTH

    ---rony

     
    • Ruurd Idenburg

      Ruurd Idenburg - 2025-11-05

      Hi Rony,

      So how does what you say about NEW agree with:

      rexxref: 4.2.5 Default search order for methods

      This search order places methods of a class before methods of its
      superclasses so that a class can
      supplement or override inherited methods.

      and

      rexxref: 4.2.9. Initialization

      Any object requiring initialization at creation time must define an INIT
      method. If this method is
      defined, the class object runs the INIT method after the object is
      created. If an object has more than
      one INIT method (for example, it is defined in several classes), each
      INIT method must forward the
      INIT message up the hierarchy to complete the object's initialization.

      ?

      Ruurd

      On 11/3/25 14:08, Rony G. Flatscher wrote:

      Hi Ruurd,

      if you study the Array class in the reference you will see that it
      defines its own NEW class method. Therefore you need to study it to
      see what it does. As you will see Array's NEW method does not send an
      INIT message to a newly created Array object.

      This is different than the behaviour of Object's NEW class method
      which will send the newly created object the INIT message with the
      received arguments in the same order, if any.

      If you want to take care of creating Array objects in a different way
      than Array's NEW class method you need to implement your own version
      of a NEW class method in your subclass.

      HTH

      ---rony


      [bugs:#2034] https://sourceforge.net/p/oorexx/bugs/2034/ Sublassing
      Array does not seem to call subclass init method before checking
      arguments

      Status: open
      Group: 5.2.0
      Created: Sat Oct 11, 2025 11:34 AM UTC by Ruurd Idenburg
      Last Updated: Fri Oct 31, 2025 09:06 AM UTC
      Owner: nobody

      Rexx version 5.1.0 64-bit on Linux Mint 21.3
      As demonstrated by the following code:
      The init method for the typedArray subclass is not called at all
      before the argumenmts for the superclass are checked.

      Ruurd Idenburg

      !/usr/bin/env rexx

      say
      say "Rexx version:".RexxInfo~version "from:" .RexxInfo~date
      say
      say "Creating a typedDirectory subclass."
      say
      myDirectory = .typedDirectory~new('Rony')
      say "This is a" myDirectory~class~id "instance"
      say
      say "Now trying to create a typedArray subclass."
      say
      myArray = .typedArray~new('Will')
      say "This is a" myArray~class~id "instance"
      exit

      ::class typedArray public subclass Array
      ::attribute type
      / instance 'init' Called with an invalid argument for the super class /
      ::method init
      say "Method 'init'' for typedArray instance"
      use strict arg type
      if "RTW"~pos(type[1]~upper)==0
      then raise syntax 93.914 array(1,"R(ony),T(im),W(ill)",type)
      / superclass 'init' called with proper argument /
      self~init:super(1)
      self~type = type
      exit

      ::class typedDirectory public subclass Directory
      ::attribute type
      / Called with an invalid argument for the super class /
      ::method init
      say "Method 'init' for typedDirectory instance"
      use strict arg type
      if "RTW"~pos(type[1]~upper)==0
      then raise syntax 93.914 array(1,"R(ony),T(im),W(ill)",type)
      / superclass 'init' called with proper argument /
      self~init:super(1)
      self~type = type
      exit


      Sent from sourceforge.net because you indicated interest in <https: sourceforge.net="" p="" oorexx="" bugs="" 2034=""></https:>

      To unsubscribe from further messages, please visit <https: sourceforge.net="" auth="" subscriptions=""></https:>

       

      Related

      Bugs: #2034

  • Rony G. Flatscher

    Hi Ruurd,

    ad "rexxref: 4.2.5 Default search order for methods": this is why it works, if you define a class method NEW for your subclass. It will be picked up before the superclass's NEW method.

    ad "rexxref: 4.2.9. Initialization": this is currently discussed on the developer list.

    HTH

    ---rony

     
    • Ruurd Idenburg

      Ruurd Idenburg - 2025-11-05

      Hi again,

      Thus if one wants to override an superclass INIT, one must define a
      class NEW method, is that what you are saying?

      That is not true for (I think all) other collections with an optional
      SIZE argument?

      Seems to me that the way a multidimensional Array can be defined causes
      the problem and it could be solved by allowing arguments after a not
      defined first argument (which would create a 1 dimensional array) and
      pass them on to the subclass INIT.

      HTH (a little joke here)

      Ruurd

      P.S. For multidimension arrays an omitted argument after the dimensions and before subclass arguments could also be feasible. This does not create regression (as far as I can tell) and impact the .ARRAY documentation only (I think).

      On 11/5/25 11:58, Rony G. Flatscher wrote:

      Hi Ruurd,

      ad "rexxref: 4.2.5 Default search order for methods": this is why it
      works, if you define a class method NEW for your subclass. It will be
      picked up before the superclass's NEW method.

      ad "rexxref: 4.2.9. Initialization": this is currently discussed on
      the developer list.

      HTH

      ---rony


      [bugs:#2034] https://sourceforge.net/p/oorexx/bugs/2034/ Sublassing
      Array does not seem to call subclass init method before checking
      arguments

      Status: open
      Group: 5.2.0
      Created: Sat Oct 11, 2025 11:34 AM UTC by Ruurd Idenburg
      Last Updated: Mon Nov 03, 2025 01:08 PM UTC
      Owner: nobody

      Rexx version 5.1.0 64-bit on Linux Mint 21.3
      As demonstrated by the following code:
      The init method for the typedArray subclass is not called at all
      before the argumenmts for the superclass are checked.

      Ruurd Idenburg

      !/usr/bin/env rexx

      say
      say "Rexx version:".RexxInfo~version "from:" .RexxInfo~date
      say
      say "Creating a typedDirectory subclass."
      say
      myDirectory = .typedDirectory~new('Rony')
      say "This is a" myDirectory~class~id "instance"
      say
      say "Now trying to create a typedArray subclass."
      say
      myArray = .typedArray~new('Will')
      say "This is a" myArray~class~id "instance"
      exit

      ::class typedArray public subclass Array
      ::attribute type
      / instance 'init' Called with an invalid argument for the super class /
      ::method init
      say "Method 'init'' for typedArray instance"
      use strict arg type
      if "RTW"~pos(type[1]~upper)==0
      then raise syntax 93.914 array(1,"R(ony),T(im),W(ill)",type)
      / superclass 'init' called with proper argument /
      self~init:super(1)
      self~type = type
      exit

      ::class typedDirectory public subclass Directory
      ::attribute type
      / Called with an invalid argument for the super class /
      ::method init
      say "Method 'init' for typedDirectory instance"
      use strict arg type
      if "RTW"~pos(type[1]~upper)==0
      then raise syntax 93.914 array(1,"R(ony),T(im),W(ill)",type)
      / superclass 'init' called with proper argument /
      self~init:super(1)
      self~type = type
      exit


      Sent from sourceforge.net because you indicated interest in <https: sourceforge.net="" p="" oorexx="" bugs="" 2034=""></https:>

      To unsubscribe from further messages, please visit <https: sourceforge.net="" auth="" subscriptions=""></https:>

       

      Related

      Bugs: #2034


      Last edit: Ruurd Idenburg 2025-11-05

Anonymous
Anonymous

Add attachments
Cancel