수색…


객체 생성하기

다른 많은 언어와 달리 Perl에는 객체에 메모리를 할당하는 생성자가 없습니다. 대신 데이터 구조를 만들고 데이터로 채우는 클래스 메소드를 작성해야합니다 (팩토리 메소드 디자인 패턴으로 알 수 있음).

package Point;
use strict;

sub new {
    my ($class, $x, $y) = @_;
    my $self = { x => $x, y => $y }; # store object data in a hash
    bless $self, $class;             # bind the hash to the class
    return $self;
}

이 방법은 다음과 같이 사용할 수 있습니다.

my $point = Point->new(1, 2.5);

화살표 연산자 -> 가 메소드와 함께 사용될 때마다 왼쪽 피연산자가 주어진 인수 목록 앞에 추가됩니다. 따라서, new 값의 @_ 에는 값 ('Point', 1, 2.5) 됩니다.

new 이름에는 특별한 것이 없습니다. 원하는 경우 팩토리 메서드를 호출 할 수 있습니다.

해시에는 특별한 것이 없습니다. 다음과 같은 방법으로 동일한 작업을 수행 할 수 있습니다.

package Point;
use strict;

sub new {
    my ($class, @coord) = @_;
    my $self = \@coord;
    bless $self, $class;
    return $self;
}

일반적으로 모든 참조는 스칼라 참조조차도 객체가 될 수 있습니다. 그러나 대부분의 경우 해시는 객체 데이터를 표현하는 가장 편리한 방법입니다.

클래스 정의하기

일반적으로 Perl 클래스는 패키지입니다. 일반 패키지와 같이 데이터와 메소드를 포함 할 수 있습니다.

package Point;
use strict;

my $CANVAS_SIZE = [1000, 1000];

sub new {
    ...
}

sub polar_coordinates {
    ...
}

1;

패키지에서 선언 된 변수는 객체 (인스턴스) 변수가 아니라 클래스 변수라는 점에 유의해야합니다. 패키지 수준 변수를 변경하면 클래스의 모든 객체에 영향을줍니다. 개체 별 데이터를 저장하는 방법은 "개체 만들기"를 참조하십시오.

클래스 패키지를 구체적으로 만드는 것은 화살표 연산자 -> 입니다. 맨손으로 사용한 후 사용할 수 있습니다.

Point->new(...);

또는 스칼라 변수 (일반적으로 참조를 보유) 뒤에 :

my @polar = $point->polar_coordinates;

화살표의 왼쪽은 메소드의 주어진 인수 목록 앞에 추가됩니다. 예를 들어, 통화 후

Point->new(1, 2);

new 배열의 @_ 에는 ('Point', 1, 2) 3 개의 인수가 포함됩니다.

클래스를 나타내는 패키지는이 규칙을 고려해야하며 모든 메서드에 추가 인수가 하나 있어야합니다.

상속 및 메서드 확인

클래스를 다른 클래스의 하위 클래스로 만들려면 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
    • Point ( Point2D 최초의 부모)
    • GeometryObject ( Point 부모)
    • PlanarObject ( Point2D 두 번째 부모)

    예를 들어, 다음 코드에서 :

    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 를 호출합니다.

클래스 및 객체 메소드

Perl에서 클래스 (정적)와 객체 (인스턴스) 메소드의 차이는 다른 언어 에서처럼 강력하지 않지만 여전히 존재합니다.

화살표 연산자의 왼쪽 피연산자 -> 는 호출 할 메소드의 첫 번째 인수가됩니다. 문자열 일 수 있습니다.

# the first argument of new is string 'Point' in both cases
Point->new(...);

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

또는 객체 참조 :

# reference contained in $point is the first argument of polar_coordinates
my $point = Point->new(...);
my @coord = $point->polar_coordinates;

클래스 메소드는 첫 번째 인수가 문자열이 될 것으로 예상하는 메소드이고 객체 메소드는 첫 번째 인수가 객체 참조가 될 것으로 기대하는 메소드입니다.

클래스 메서드는 일반적으로 클래스의 이름 인 첫 번째 인수로는 아무 것도 수행하지 않습니다. 일반적으로 Perl 자체에서만 메서드 확인에 사용됩니다. 따라서 일반적인 클래스 메서드를 개체에 대해서도 호출 할 수 있습니다.

my $width = Point->canvas_width;

my $point = Point->new(...);
my $width = $point->canvas_width;

이 구문은 허용되지만 종종 혼동을 줄 수 있으므로이를 피하는 것이 좋습니다.

객체 메소드는 객체 참조를 첫 번째 인수로받습니다. 따라서 클래스 메소드와 달리 객체 데이터를 처리 할 수 ​​있습니다.

package Point;
use strict;

sub polar_coordinates {
    my ($point) = @_;
    my $x = $point->{x};
    my $y = $point->{y};
    return (sqrt($x * $x + $y * $y), atan2($y, $x));
}

1;

같은 방법으로 두 경우를 추적 할 수 있습니다 : 클래스 또는 객체 메소드로 호출되는 경우 :

sub universal_method {
    my $self = shift;
    if (ref $self) {
        # object logic
        ...
    }
    else {
        # class logic
        ...
    }
}

현대 Perl에서 클래스 정의하기

사용 가능하지만, 처음부터 클래스 정의하는 것은 현대 Perl에서는 권장되지 않습니다. 더 많은 기능과 편리함을 제공하는 도우미 OO 시스템 중 하나를 사용하십시오. 이러한 시스템에는 다음이 있습니다.

엘크

package Foo;
use Moose;

has bar => (is => 'ro');                 # a read-only property
has baz => (is => 'rw', isa => 'Bool');  # a read-write boolean property

sub qux {
    my $self = shift;
    my $barIsBaz = $self->bar eq 'baz';  # property getter
    $self->baz($barIsBaz);               # property setter
}

클래스 :: 접근 자 (무스 문법)

package Foo;
use Class::Accessor 'antlers';

has bar => (is => 'ro');                 # a read-only property
has baz => (is => 'rw', isa => 'Bool');  # a read-write property (only 'is' supported, the type is ignored)

클래스 :: 접근 자 (기본 구문)

package Foo;
use base qw(Class::Accessor);

Foo->mk_accessors(qw(bar baz));  # some read-write properties
Foo->mk_accessors(qw(qux));      # a read-only property

클래스 :: Tiny

package Foo;
use Class::Tiny qw(bar baz);  # just props

역할

Perl에서의 역할은 근본적으로

  • 메소드와 속성 세트.
  • 수업에 직접 주입.

역할은 모든 클래스 (역할을 소비 한다고 말함 )에 구성 되거나 적용될 수있는 기능을 제공합니다. 역할은 상속 될 수 없지만 다른 역할에 의해 소비 될 수 있습니다.

역할은 소비 클래스가 메서드 자체를 구현하는 대신 (Java 또는 C #의 인터페이스와 마찬가지로) 일부 메서드를 구현 해야 할 수도 있습니다.

Perl에는 역할에 대한 지원 기능이 기본적으로 없지만 이러한 지원을 제공하는 CPAN 클래스가 있습니다.

무스 :: 역할

package Chatty;
use Moose::Role;

requires 'introduce';  # a method consuming classes must implement

sub greet {            # a method already implemented in the role
    print "Hi!\n";
}


package Parrot;
use Moose;

with 'Chatty';

sub introduce {
    print "I'm Buddy.\n";
}

역할 :: 작은

OO 시스템이 역할 (예 : Class::Accessor 또는 Class::Tiny )에 대한 지원을 제공하지 않는 경우에 사용하십시오. 속성을 지원하지 않습니다.

package Chatty;
use Role::Tiny;

requires 'introduce';  # a method consuming classes must implement

sub greet {            # a method already implemented in the role
    print "Hi!\n";
}

package Parrot;
use Class::Tiny;
use Role::Tiny::With;

with 'Chatty';

sub introduce {
    print "I'm Buddy.\n";
}


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow