內容

名稱

perlclass - Perl 類別語法參考

語法

use v5.38;
use feature 'class';

class My::Example 1.234 {
    field $x;

    ADJUST {
        $x = "Hello, world";
    }

    method print_message {
        say $x;
    }
}

My::Example->new->print_message;

說明

本文件說明 Perl 的 class 功能語法,它提供支援物件導向程式設計範例的原生關鍵字。

歷史

自 Perl 5 以來,物件的支援圍繞著使用套件名稱來「祝福」參考的概念。此類參考可用於呼叫其被祝福套件(或其任何父系)的子常式。此系統儘管基礎,但靈活性足以允許建立多個更進階的社群驅動物件導向系統。

類別功能是類別語法的核心實作,它與在其他程式語言中發現的類似。它不是 bless 包裝器,而是直接建置在 perl 詮釋器中的全新系統。

關鍵字

啟用 class 功能允許在目前套件的範圍內使用下列新的關鍵字

class

class NAME BLOCK

class NAME VERSION BLOCK

class NAME;

class NAME VERSION;

class 關鍵字宣告一個新的套件,其預計為一個類別。class 功能中的所有其他關鍵字都應在此宣告的範圍內使用。

class WithVersion 1.000 {
    # class definition goes here
}

類別可以在區塊或陳述句語法中宣告。如果使用區塊,區塊的主體會包含類別的實作。如果使用陳述句形式,檔案的其餘部分會使用到下一個 classpackage 陳述句為止。

classpackage 宣告很類似,但類別會自動取得一個名為 new 的建構函式 - 您不需要 (也不應該) 撰寫一個。此外,在類別區塊中,您被允許宣告欄位和方法。

field

field VARIABLE_NAME;

field VARIABLE_NAME = EXPR;

field VARIABLE_NAME : ATTRIBUTES;

field VARIABLE_NAME : ATTRIBUTES = EXPR;

欄位是在類別範圍內可見的變數 - 更具體地說,是在 "method"ADJUST 區塊內。每個類別實例都會取得它們自己的欄位儲存,彼此獨立。

欄位表現得像一個正常的詞彙範圍變數。它有一個符號,而且是類別的私有 (儘管建立一個存取器方法會讓它從外部可存取)。主要差異在於不同的實例會在同一個範圍內存取不同的值。

class WithFields {
    field $scalar = 42;
    field @array  = qw(this is just an array);
    field %hash   = (species => 'Martian', planet => 'Mars');
}

欄位可以選擇性地有初始化表達式。如果存在,表達式會在每個物件實例的建構函式中評估。在每個評估期間,表達式可以使用任何先前設定欄位的值,以及看到範圍內的任何其他變數。

class WithACounter {
    my $next_count = 1;
    field $count = $next_count++;
}

當與 :param 欄位屬性結合使用時,預設表達式可以使用 =//=||= 這些運算子。使用 = 的表達式會在呼叫者完全未將對應參數傳遞給建構函數時套用。使用 //= 的表達式也會在呼叫者傳遞參數但值未定義時套用,而使用 ||= 的表達式會在值為 false 時套用。

方法

method METHOD_NAME SIGNATURE BLOCK

method METHOD_NAME BLOCK

method SIGNATURE BLOCK

method BLOCK

方法是預計在類別物件的內容中呼叫的子常式。

一個名為 $self 的變數會自動建立在 method 的詞彙範圍中,並填入目前的物件執行個體。

方法總是作用於 use feature 'signatures' 生效時,但 $self 對於簽章而言不會出現在引數清單中。

class WithMethods {
    field $greetings;

    ADJUST {
        $greetings = "Hello";
    }

    method greet($name = "someone") {
        say "$greetings, $name";
    }
}

就像一般子常式一樣,方法可以是匿名的

class AnonMethodFactory {

    method get_anon_method {
        return method {
            return 'this is an anonymous method';
        };
    }
}

屬性

上述關鍵字的特定面向是使用屬性來管理的。所有屬性都以冒號開頭,而且可以在項目名稱後附加一個或多個屬性,並以空格分隔。

類別屬性

:isa

類別可以使用 :isa 類別屬性繼承自一個超類別。

class Example::Base { ... }

class Example::Subclass :isa(Example::Base) { ... }

繼承的方法是可見的,而且可以呼叫。欄位總是詞彙的,因此無法透過繼承看到。

:isa 屬性可以要求基本類別的最低版本;它套用的方式類似於 use - 如果提供的版本太低,它會在編譯時失敗。

class Example::Subclass :isa(Example::Base 2.345) { ... }

如果 :isa 屬性尚未載入,它會嘗試require 命名模組。

欄位屬性

:param

具有 :param 屬性的純量欄位會從傳遞給建構函數的命名參數取得其值。預設情況下,參數的名稱會與欄位相同(減去其開頭的 $ 標誌),但可以在屬性中指定不同的名稱。

field $x :param;
field $y :param(the_y_value);

如果沒有預設表達式,則建構函數需要參數;呼叫者必須傳遞參數,否則會擲回例外。有了預設表達式,這就會變成可選的。

方法屬性

目前沒有。

物件生命週期

建構

每個物件都從建構式呼叫開始其生命週期。建構式總是命名為 new,並像在類別名稱上呼叫方法一樣被呼叫

my $object = My::Class->new(%arguments);

在建構期間,類別欄位會與 %arguments hash 進行比較,並在可能的情況下填入資料。

調整

物件調整可以在建構期間執行,以執行使用者定義的程式碼。這是透過 ADJUST 區塊來完成,這些區塊會按照宣告順序呼叫。

它們類似於在封裝編譯期間執行的 BEGIN 區塊。但是,它們也可以存取 $self 詞彙 (物件實例) 和所有到目前為止建立的物件欄位。

生命週期

在建構階段之後,物件就可以準備好使用。

對物件使用 blessed (Scalar::Util::blessedbuiltin::blessed) 會傳回類別名稱,而 reftype (Scalar::Util::reftypebuiltin::reftype) 會傳回字串 'OBJECT'

銷毀

就像其他參考一樣,當物件參考計數達到零時,它將自動被銷毀。

待辦事項

此功能仍處於實驗階段,且非常不完整。下列清單概述了仍需新增或變更的作業類型

作者

Paul Evans

Bartosz Jarzyna