Hamish, There are lots of ways to do object orientedness and inheritance. How you do it depends very much on the problem(s) you are trying to solve, and often on personal style...I'll try to answer your questions in-line.
Hamish Whittal <[EMAIL PROTECTED]> writes: > Hi Folks, > > I have an object called Cisco:cs2600. I have a constructor that will new > that will initialise all the object with all the relavant information. > > Now, I call the constructor to create a new instance of this object. > > $deviceType = Cisco::cs2600->new($systemObjectID); > > So, now I have an object of a Cisco 2600. But that is not what I am > looking to manipulate. That mearly tells me what I can do with this type > of device. What I would like is to create an instance of a Cisco 2600 > type..... > The specific instance will have an IP address, Community string, etc. > associated with it. > > So, > > $device = Device->new($IPAddress, $CommunityString). > > QUESTION1: I have declared Cisco::cs2600 class, can I just declare a > class called Device, or should it be Cisco::Device? Well, is a 'Device' a generic thing, which Cisco::cs2600 is a kind of? Or is 'Device' a part of a 'Cisco::cs2600'? Or is 'Device' a specific kind of 'Cisco::cs2600'? To pick the correct class relationship, it usually helps to work out what the 'real life' relationships between the objects you are modeling is. Things like "a frumple is a kind of widget", "all snaz's contain a bar". In this case, I'm guessing that the following statements are true: 'A cs2600 is a kinda of Cisco Device', 'We may be modeling more than one type of Cisco Device', and 'We may have to model Devices which are of a different kind than Cisco.' Given the above, and according to my personal style, I would make the following directories/files: NetDevice/ NetDevice.pm NetDevice/Cisco/ NetDevice/Cisco/cs2600.pm And set things up so that the top part of 'cs2600.pm' looks like this: <code> package NetDevice::Cisco::cs2600; use strict; use warnings; use NetDevice; our @ISA = qw/NetDevice/; __END__ </code> Notice I'm leaving out a 'Cisco.pm' - I don't have enough meat yet to justify it. If I had stuff which was specific to Cisco devices, I would create Cisco.pm and modify the above file appropriately. > Now I know this is inheritance, and I know I should just include an ISA > in the top of the Device package like so: > > package Device; > use strict; > > @Device::ISA = qw( Cisco::cs2600 ); I think 'our @ISA = qw/Cisco::cs2600/;' is a more common syntax, but I think the above works just as well. > sub new { > $self = $_[0]; > bless { _ipaddress = $_[1], > _community = $_[2] > }; > } I don't think the above code works, but perhaps I'm missing something. Usually a standard 'new' looks more like this: sub new { my $class = shift; my @attr = @_; my $self = bless {_ipaddress => $attr[0], _community => $attr[1], }, $class; return $self; } > QUESTION2: If I would like to initialise the DeviceType when should it > be done? > > So for example, I have 10 devices all with different IPAddresses and > Community strings, but all Cisco 2600's, should I do this: > > $deviceType = Cisco::cs2600->new($systemObjectID); > foreach $IPAddress ( keys %{$All_Network_Switches} ) { > $kit = Device->new($IPAddress, $All_Network_Switches{$IPAddress}); > .....do something with this kit, then get the next one..... > } I think that this would work with the scheme you mention above, but you aren't using '$deviceType' - none of the '$kit's would have any notion of being a Cisco::cs2600. I would do the above like so: foreach $IPAddress ( keys %{$All_Network_Switches} ) { $kit = NetDevice::Cisco::cs2600->new($IPAddress, $All_Network_Switches{$IPAddress}); .....do something with this kit, then get the next one..... } However, there's a problem - the 'new' sub I wrote above doesn't know how to handle systemObjectID's - which is one of the data members of the Cisco device you described above. I've included a couple of files at the bottom which show the way I've been solving this problem lately. > Finally, in the '....do something with this kit,.....', I would like to > get certain attributes for the deviceType, could I do something like > > Device->get_DeviceType_information(); > and this would call the method from Cisco::cs2600. If 'Device' ISA 'Cisco::cs2600', then yes, this would work. (This is a class method, btw.) > Thanks in advance for reading to here. As a special addition to the > persistent reader, I give you this special gift....a 1 year subscription > to all my received spam ;-). Only kidding. I'd like to finish responding to your question with some code, and another question. The code is what I came up with after thinking about your problem. It may not be the right setup for your situation. It follows the template I've been using lately for objects with an 'is a kind of' relationship. It certainly isn't production-ready as-is. What it does do is show how I solve the problem of the parent's classes 'new' not knowing about data members needed for the children. The code below is missing a lot of stuff - like parameter validation, for instance (I usually use Params::Validate, but didn't want to complexitify this code any more). The question is: what improvements do people see for this? Is there a better way? Is the code below too complex for simple classes? Using the directory structure above: NetDevice.pm: package NetDevice; use strict; use warnings; my %valid_fields = (ipaddress => undef, community => undef, ); sub valid_fields { return (%valid_fields) }; sub new { my $class = shift; my %attr = @_; my $fields = {$class->valid_fields}; my $self = bless { %{$fields} }, $class; foreach (keys %{$fields}) { if (exists $attr{$_}) { $self->$_($attr{$_}); } } $self->_init; # class-specific init code return $self; } sub _init { }; #empty for the base class sub ipaddress { my $self = shift; my $ip = shift; if (defined $ip) { $self->{ipaddress} = $ip; } return $self->{ipaddress}; } sub community { my $self = shift; my $community = shift; if (defined $community) { $self->{community} = $community; } return $self->{community}; } 1; __END__ NetDevice/Cisco/cs2600.pm: package NetDevice::Cisco::cs2600; use strict; use warnings; use NetDevice; our @ISA = qw/NetDevice/; my %valid_fields = (object_id => undef, ); sub valid_fields { return (shift->SUPER::valid_fields(), %valid_fields) } sub object_id { my $self = shift; my $id = shift; if (defined $id) { $self->{object_id} = $id; } return $self->{object_id}; } 1; __END__ testme.pl: use Data::Dumper; use NetDevice::Cisco::cs2600; my $cisco = new NetDevice::Cisco::cs2600(ipaddress => "200.12.1.50", object_id => 57); print "$cisco\n"; print Data::Dumper->Dump([($cisco)]); Output of the above: $ perl testme.pl NetDevice::Cisco::cs2600=HASH(0x815708c) $VAR1 = bless( { 'community' => undef, 'ipaddress' => '200.12.1.50', 'object_id' => 57 }, 'NetDevice::Cisco::cs2600' ); Hrm. Now that post was longer than I expected it to be. :-) -RN -- Robin Norwood Red Hat, Inc. "The Sage does nothing, yet nothing remains undone." -Lao Tzu, Te Tao Ching -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]