2017-06-14 138 views
4

有沒有辦法從子類中的構造函數中分配在超類中聲明的實例變量?我已經習慣使用BUILD()作爲構造函數,但是我想知道這是否是一個好主意。 I.e:Perl6:子類中的構造函數

use v6;  

class File                                                          
{                                                            
    has $!filename;                                                
}                                                                                                                      

class XmlFile is File                                                       
{                                                            
    submethod BUILD(:$!filename)                                                    
    { 
    } 
} 

my XmlFile $XF = XmlFile.new(filename => "test.xml"); 

上面的代碼不起作用,提示錯誤:「屬性$!文件名未在類XmlFile中聲明」。這是使用正確的accesser的問題嗎?改變「!」至 」。」並不能解決問題。

回答

4

你在這裏一半。你必須做出正確的更改您的代碼:

class File { 
    has $.filename;     # 1. Replace `!` with `.` 
} 

class XmlFile is File { 
    submethod BUILD(:$filename) { } # 2. Remove `!` 
} 

dd my XmlFile $XF = XmlFile.new(filename => "test.xml"); 

# XmlFile $XF = XmlFile.new(filename => "test.xml") 

File類更換$!filename$.filename生成該類中的公共訪問方法(.filename)。

(注:屬性在技術上總是私人的一類,即始終無法提供其他類,甚至trusted的。當你看到「公共屬性」的真正含義有一個「公開訪問」控制訪問到對應的下層專用屬性。)

BUILD簽名卸下! twigil在XmlFile類意味着你不再試圖引用不存在的XmlFile屬性,而不是僅僅通過命名參數。

Object Construction

Due to the default behavior of BUILDALL and BUILD submethods, named arguments to the constructor new derived from Mu can correspond directly to public attributes of any of the classes in the method resolution order, or to any named parameter of any BUILD submethod.

(有這個「公共屬性」用詞不當,它的意思是「匹配的公共訪問屬性」。)

+0

的確是的:)謝謝。 – Mikkel

0

如果你想它不公開,你可以總是將其直接添加到子類中。 (也許你不控制你正在繼承的類)當然,你將必須小心哪些方法做你的類和子類之間的事情。

class File                                                          
{                                                            
    has $!filename;                                                
}                                                                                                                      

class XmlFile is File                                                       
{ 
    has $!filename; 

    submethod BUILD(:$!filename)                                                    
    { 
    } 
} 

my XmlFile $XF = XmlFile.new(filename => "test.xml"); 

您可能還需要考慮使用「有」關係,而不是一個「是」,方法是將該持有class File取決於您正在嘗試做的class XmlFile的屬性關係。

handles特徵使委派到另一個類是一個特別容易和有用的選項來指導子類化。