继承和方法解决

要使类成为另一个类的子类,请使用 parent pragma:

package Point;
use strict;
...
1;

package Point2D;
use strict;
use parent qw(Point);
...
1;

package Point3D;
use strict;
use parent qw(Point);
...
1;

Perl 允许多重继承:

package Point2D;
use strict;
use parent qw(Point PlanarObject);
...
1;

继承是关于在特定情况下调用哪种方法的解决方案。由于纯 Perl 没有规定有关用于存储对象数据的数据结构的任何规则,因此继承与此无关。

考虑以下类层次结构:

package GeometryObject;
use strict;

sub transpose { ...}

1;

package Point;
use strict;
use parent qw(GeometryObject);

sub new { ... };

1;

package PlanarObject;
use strict;
use parent qw(GeometryObject);

sub transpose { ... }

1;

package Point2D;
use strict;
use parent qw(Point PlanarObject);

sub new { ... }

sub polar_coordinates { ... }

1;

方法解析的工作原理如下:

  1. 起点由箭头运算符的左操作数定义。

    • 如果是一个简单的话:

      Point2D->new(...);
      

      …或者是一个包含字符串的标量变量:

      my $class = 'Point2D';
      $class->new(...);
      

      …然后起点是具有相应名称的包(在两个示例中都是 Point2D)。

    • 如果左操作数是一个标记变量,包含一个受祝福的引用:

      my $point = {...};
      bless $point, 'Point2D'; # typically, it is encapsulated into class methods
      my @coord = $point->polar_coordinates;
      

      然后起点是参考的类(再次,Point2D)。箭头操作符不能用来呼吁方法 unblessed 引用。

  2. 如果起点包含所需方法,则只需调用它。

    因此,由于 Point2D::new 存在,

    Point2D->new(...);
    

    简单地称之为。

  3. 如果起点不包含所需方法,则执行 parent 类中的深度优先搜索。在上面的示例中,搜索顺序如下:

    • Point2D
    • PointPoint2D 的第一任父母)
    • GeometryObjectPoint 的父母)
    • PlanarObject(tihuan 的第二个父母 12)

    例如,在以下代码中:

    my $point = Point2D->new(...);
    $point->transpose(...);
    

    将要调用的方法是 GeometryObject::transpose,即使它将在 PlanarObject::transpose 中被覆盖。

  4. 你可以明确设置起点。

    在前面的示例中,你可以像这样显式调用 PlanarObject::transpose

    my $point = Point2D->new(...);
    $point->PlanarObject::transpose(...);
    
  5. 以类似的方式,SUPER::在当前类的父类中执行方法搜索。

    例如,

    package Point2D;
    use strict;
    use parent qw(Point PlanarObject);
    
    sub new {
        (my $class, $x, $y) = @_;
        my $self = $class->SUPER::new;
        ...
    }
    
    1;
    

    将在 Point2D::new 执行过程中调用 Point::new