Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Nested Class Instances not assignable

    I seem to have a generic problem: if one user-created class is meant to contain an instance of another user created class, it can't be assigned. A blank member instance is created whenever the containing class is instantiated, but no matter what I've tried, it can't ever be replaced.

    Code:
    : mata clear
    
    : class Inner {
    >         void speak()
    >         string scalar toSay
    >         void new()
    > }
    
    : void Inner::new() {
    >         "creating inner instance"
    > }
    
    : void Inner::speak() {
    >         this.toSay
    > }
    
    : class Outer {
    >         class Inner scalar i
    >         void speak()
    >         void setInner()
    > }
    
    : void Outer::speak() {
    >         this.i.speak()
    > }
    
    : void Outer::setInner(class Inner inner) {
    >         this.i = inner
    > }
    
    : 
    : inner = Inner()
      creating inner instance
    
    : inner.toSay = "hello!"
    
    : inner.speak()
      hello!
    
    : outer = Outer()
      creating inner instance
    
    : outer.setInner(inner)
      creating inner instance
           Outer::setInner():  3011  invalid lval
                     <istmt>:     -  function returned error
    Obviously, there are better ways to accomplish this particular task, but when what I want to program follows something like a functional paradigm (java users will think of the ubiquitous Runnable interface), this really is the best way to test.

  • #2
    Okay, I figured out that my problem is that I didn't know how to use pointers. One correct way of doing this:

    Code:
    : mata clear
    
    : 
    : class Inner {
    >         void speak()
    >         string scalar toSay
    >         void new()
    > }
    
    : void Inner::new() {
    >         "creating inner instance"
    > }
    
    : void Inner::speak() {
    >         this.toSay
    > }
    
    : 
    : struct InnerStructWrapper {
    >         class Inner scalar i
    > }
    
    : 
    : class Outer {
    >         void speak()
    >         void setInner()
    >         pointer(class Inner scalar) scalar inner
    > }
    
    : void Outer::speak() {
    >         (*inner).speak()
    > }
    
    : void Outer::setInner(pointer(class Inner scalar) inner_) {
    >         this.inner = inner_
    > }
    
    : 
    : inner = Inner()
      creating inner instance
    
    : inner.toSay = "hello!"
    
    : inner.speak()
      hello!
    
    : outer = Outer()
    
    : outer.setInner(&inner)
    
    : outer.speak()
      hello!
    Other, possibly simpler ways can be found in the ftof section of the mata reference manual.

    Comment


    • #3
      Hi David
      Thank you for this example on how to use classes.
      I too would have expected that a class variable defined as a class would have been enough.
      I've made an another example below and from that I've got the following comments:
      • You do not need to pass a class pointer as an argument as seen in method add_animal
      • Class arguments can not be optional arguments
      • It seems like one has to go through a locally defined class variable to retrieve a class from a class vector
      • When you read the documentation and have one line methods/functions in examples: Loose the curly brackets
      That's it for now.


      Code:
      :         class animal {
      >                 virtual void sound()
      >                 void being_poked()
      >         }
      :                 void animal::sound() "Super class animal: Sound not implemented" 
      :                 
      :                 void animal::being_poked()
      >                 {
      >                         sound()
      >                         "Do not poke me!!"
      >                 }
      : 
      :         class cow extends animal {
      >                 void new()
      >                 virtual void sound()
      >         }
      :                 void cow::new() "I'm a cow"
      :                 void cow::sound() "Mo!"
      : 
      :         class sheep extends animal {
      >                 void new()
      >                 virtual void sound()
      >         }
      :                 void sheep::new() "I'm a sheep"
      :                 void sheep::sound() "Baa!"
      : 
      :         
      :         class farmer{
      >                 pointer vector animals
      >                 void add_animal()
      >                 void poking_animals()
      >         }
      :                 // class scalars may not be received as optional arguments.
      :                 void farmer::add_animal(class animal scalar a) this.animals = this.animals, &a
      :                 void farmer::poking_animals() { 
      >                         class animal scalar a
      > 
      >                         for (r=1;r<=cols(this.animals);r++) {
      >                                 a = *this.animals[r]
      >                                 a.being_poked()
      >                         }
      >                 }
      :         
      :         c = cow()
        I'm a cow
      :         s = sheep()
        I'm a sheep
      :         f = farmer()
      :         f.add_animal(c)
      :         f.add_animal(s)
      :         f.poking_animals()
        Mo!
        Do not poke me!!
        Baa!
        Do not poke me!!
      Kind regards

      nhb

      Comment

      Working...
      X