Наследование

Объектно Ориентированное Программирование определяет концепцию наследования как как механизм для повторного использования кода. Perl 6 поддерживает как наследование одного класса от другого, так и множественное наследование ( от нескольких классов ).Когда класс наследуется от другого, диспетчер методов следует по цепочке наследования, чтобы определить метод для вызова. Это поведение одинаково как для определенных стандартным способом, с помощью ключевого слова method, так и для генерируемых методов для доступа к свойствам объекта (attribute accessors).

    class Employee {
        has $.salary;

        method pay() {
            say "Here is \$$.salary";
        }

    }

    class Programmer is Employee {
        has @.known_languages is rw;
        has $.favorite_editor;

        method code_to_solve( $problem ) {
            say "Solving $problem using $.favorite_editor in " 
            ~ $.known_languages[0] ~ '.';
        }
    }

Теперь любой объект типа Programmer может использовать методы и аксессоры ( методы для доступа к атрибутам ), определенные в классе Employe, так словно они определены в классе Programmer.

    my $programmer = Programmer.new(
        salary => 100_000, 
        known_languages => <Perl5 Perl6 Erlang C++>,
        favorite_edtor => 'vim'
    );

    $programmer.code_to_solve('halting problem');
    $programmer.pay();

Переопределение унаследованных методов

Классы могут перекрывать методы и атрибуты родительских классов определяя свои собственные. Следующий пример демонстрирует как в классе Baker переопределяется метод cook класса Cook.

    class Cook is Employee {
        has @.utensils  is rw;
        has @.cookbooks is rw;

        method cook( $food ) {
            say "Cooking $food";
        }

        method clean_utensils {
            say "Cleaning $_" for @.utensils;
        }
    }

    class Baker is Cook {
        method cook( $confection ) {
            say "Baking a tasty $confection";
        }
    }

    my $cook = Cook.new( 
        utensils => (<spoon ladel knife pan>), 
        cookbooks => ('The Joy of Cooking'), 
        salary => 40000);

    $cook.cook( 'pizza' ); # Cooking pizza

    my $baker = Baker.new(
        utensils => ('self cleaning oven'), 
        cookbooks => ("The Baker's Apprentice"), 
        salary => 50000);

    $baker.cook('brioche'); # Baking a tasty brioche

Диспетчер методов в процессе определения метода для вызова останавливается на методе cook класса Baker и прекращает дальнейший просмотр родительских классов.

Множественное наследование

Как было сказано ранее, класс может наследоваться от множества классов. В таких случаях диспетчер методов будет просматривать родительские классы в поисках метода для вызова. В Perl 6 используется алгоритм C3 для линеаризации иерархии множественного наследования, что дает значительное улучшение данной функциональности в сравнении с Perl 5.

    class GeekCook is Programmer is Cook {
        method new( *%params ) {
            push( %params<cookbooks>, "Cooking for Geeks" );
            return self.bless(%params);
        }
    }

    my $geek = GeekCook.new( 
        books           => ('Learning Perl 6'), 
        utensils        => ('blingless pot', 'knife', 'calibrated oven'),
        favorite_editor => 'MacVim',
        known_languages => <Perl6>
    );

    $geek.cook('pizza');
    $geek.code_to_solve('P =? NP');

Теперь все методы из классов Programmer и Cook доступны в GeekCook.

Множественное наследование является хорошей концепцией и полезно знать о такой возможности. Понимание ее работы полезно при изучении других замечательных концепций OOП, таких как роли. Подробнее о ролях речь пойдет в соответствующей главе.