Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

The @ISA variable is a package variable that is used by all classes to indicate the class's parent (or parents). While this variable can be safely read to learn a class's inheritence inheritance hierarchy, it must not be modified at runtime [Conway 052005].

Noncompliant Code Example (@ISA)

This noncompliant code example defines a base class and an object class with simple methods:

Code Block
bgColor#ffcccc
langperl
{
  package Base;

  sub new {
    my $class = shift;
    my $self = {}; # no parent
    bless $self, $class;
    print "new Base\n";
    return $self;
  };

  sub base_value {return 1;}
}


{
  package Derived;
  our @ISA = qw(Base);  # establishes inheritenceinheritance

  sub new {
    my $class = shift;
    my $self = $class->SUPER::new(@_);  # relies on established inheritenceinheritance
    print "new Derived\n";
    return $self;
  };

  sub derived_value {return 2;}
}


BEGIN {
  my $derived = Derived->new();
  my $b = $derived->base_value();
  my $d = $derived->derived_value();
  print "base_value = $d$b\n";
  print "derived_value = $d\n";
}

When the code is run, we get a program error:

...

This error occurs because the BEGIN block is evaluated at the beginning of run timeruntime, before the @ISA statement can be evaluated. ThereforeConsequently, when the Derived::new() constructor is invoked, the Derived class has an empty parents list , and therefore fails to invoke Base::new().

Compliant Solution (

...

parent)

This compliant solution uses the base parent module rather than directly modifying the @ISA variable.

Code Block
bgColor#ccccff
langperl
# ... package Base is unchanged

{
  package Derived;
  use baseparent qw(Base);

  sub new {
    my $class = shift;
    my $self = $class->SUPER::new(@_);  # relies on established inheritenceinheritance
    print "new Derived\n";
    return $self;
  };

  sub derived_value {return 2;}
}

# ... The rest of the code is unchanged

The base parent module establishes the inheritence inheritance hierarchy at parse time, before any runtime code, including the BEGIN block, is evaluated. Therefore, when When the Derived::new() constructor is invoked, Perl knows that Derived is an instance of Base, and the program produces the correct output:

Code Block
new Base
new Derived
derivedbase_value = 21
basederived_value = 1
2

Risk Assessment

Modifying class inheritence inheritance at runtime can introduce subtle bugs , and is usually a sign of poor design.

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

OBJ30OOP00-PL

lowLow

unlikelyUnlikely

lowLow

{*}P3

L1L3

Automated Detection

Tool

Diagnostic

Perl::Critic

ClassHierarchies::ProhibitExplicitISA

Bibliography

...

...

 

...

Image Added Image Added Image Added [CPAN] Dolan, Chris. base
[CPAN] Garcia-Suarez, Rafaël, Lateur, Bart, Maischein, Max, Siegel, Anno, Schwern, Michael parentImage Removed      02. Expressions      EXP31-PL. Do not use the two-argument form of open()