2

In namespace ::NodeTypes I have a class NodeType1 and another object of another class NodeType2.

I also have a class NetworkCollector and another object of another class NodeType2

I need to pass the objects of NodeType1 and NodeType2 as parameters in object of NetworkCollector and use the functions of the passed objects within the NetworkCollector class.

Could you please suggest some possible solution of how to pass a reference for one object to another method in another class. The following sample code does not work:

itcl::class ::NodeTypes::NodeType1 {
  private activeChannels 0;
  method addChannels {numChannels} {
      #set active channels
      set activeChannels $numChannels
  }   
      method getActiveChannels {} {
        # return number of channels being used in the NodeType1 object
        return $activeChannels
      }
}

itcl::class ::NodeTypes::NodeType2 {
  private activeChannels 0;
  method addChannels {numChannels} {
      #set active channels
      set activeChannels $numChannels
  }
  method getActiveChannels {} {
      # return number of channels being used in the NodeType2 object
      return $activeChannels
  }
}

::NodeTypes::NodeType2 NodeType2Object2

itcl::class ::NodeTypes:NetworkCollector {
  method getTotalUsedChannels {Node1 Node2} {
      set Node1Channels [Node1 getActiveChannels] 
      set Node2Channels [Node2 getActiveChannels] 
      set totalActiveChannels [$Node1Channels + $Node2Channels]
      puts "Total active channels are $totalActiveChannels"
  }   
}

#creating objects
::NodeTypes::NodeType1 NodeType1Object
::NodeTypes::NodeType2 NodeType2Object

#adding channels to nodes
NodeType1Object::addChannels 5 
NodeType2Object::addChannels 10

#calculating total active channels
::NodeTypes:NetworkCollector networkCollector1

networkCollector1 getTotalUsedChannels $NodeType1Object $NodeType2Object

Problem: Error thrown----->can't read "NodeType1Object": no such variable

Could you please suggest some possible solution of how to pass a reference for one object to another method in another class.

Ulysses
  • 5,616
  • 7
  • 48
  • 84

3 Answers3

1

The silly thing is… your code is almost right (so far as I can see). You just need to be aware that adding numbers in Tcl is done with the expr command, and that variables always have to be explicitly dereferenced when you read them (i.e., $foo means exactly “read the value out of variable foo”):

set Node1Channels [$Node1 getActiveChannels] 
set Node2Channels [$Node2 getActiveChannels] 
set totalActiveChannels [expr {$Node1Channels + $Node2Channels}]

You could also have written that method like:

method getTotalUsedChannels {Node1 Node2} {
    set numChans [$Node1 getActiveChannels] 
    incr numChans [$Node2 getActiveChannels] 
    puts "Total active channels are $numChans"
}
Donal Fellows
  • 133,037
  • 18
  • 149
  • 215
1

Issue 1

In addition to what Donal said, Since getTotalUsedChannels is called directly from a class, and not part of any object, you should make it a public proc:

public proc getTotalUsedChannels ....

instead of

method getTotalUsedChannels ....

Invoke it like so:

::NodeTypes:NetworkCollector::getTotalUsedChannels NodeType1Object NodeType2Object

Issue 2

Instead of:

private activeChannels 0;

You need the keyword variable:

private variable activeChannels 0
Hai Vu
  • 37,849
  • 11
  • 66
  • 93
1

OK .. solution is simple .. adding dollar sign $ against the objects in the proc where they are passed by ref - Thanks Donal i.e.

method getTotalUsedChannels {Node1 Node2} {

set Node1Channels [$Node1 getActiveChannels]

set Node2Channels [$Node2 getActiveChannels] ...

packa r Itcl
namespace eval NodeTypes {}
itcl::delete class NodeTypes::NodeType1
itcl::delete class NodeTypes::NodeType2
itcl::delete class NodeTypes::NetworkCollector
itcl::delete class NodeTypes::NodeBase


itcl::class NodeTypes::NodeType1 { 
  private variable activeChannels 0;

  method addChannels {numChannels} {
      #set active channels
      set activeChannels $numChannels
  }

  method getActiveChannels {} {
      # return number of channels being used in the NodeType1 object
      return $activeChannels
    }
}

itcl::class NodeTypes::NodeType2 { 
  private variable activeChannels 0;
  method addChannels {numChannels} {
      #set active channels
      set activeChannels $numChannels
  }
  method getActiveChannels {} {
      # return number of channels being used in the NodeType2 object
      return $activeChannels
  }
}


itcl::class NodeTypes::NetworkCollector {
  method getTotalUsedChannels {Node1 Node2} {
      set Node1Channels [$Node1 getActiveChannels] 
      set Node2Channels [$Node2 getActiveChannels] 
      set totalActiveChannels [expr $Node1Channels + $Node2Channels]
      puts "Total active channels are $totalActiveChannels"
  }   
}

#creating objects
NodeTypes::NodeType1 NodeType1Object
NodeTypes::NodeType2 NodeType2Object

#adding channels to nodes
NodeType1Object addChannels 9
NodeType2Object addChannels 10

#calculating total active channels
NodeTypes::NetworkCollector networkCollector1

networkCollector1 getTotalUsedChannels NodeType1Object NodeType2Object
Ulysses
  • 5,616
  • 7
  • 48
  • 84