2017-06-14 3 views
4

Gibt es eine Möglichkeit, Instanzvariablen in einer Superklasse deklariert, von einem Konstruktor in einer Unterklasse? Ich habe mich daran gewöhnt, BUILD() als Konstruktor zu benutzen, aber ich frage mich, ob das eine gute Idee ist. Das heißt:Perl6: Konstruktoren in Unterklassen

use v6;  

class File                                                          
{                                                            
    has $!filename;                                                
}                                                                                                                      

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

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

Der obige Code funktioniert nicht, einen Fehler auffordert: "Attribut $ Dateiname nicht in der Klasse XMLFILE erklärt!". Geht es darum, den richtigen Zuhörer zu benutzen? Ändern "!" zu "." löst das Problem nicht.

Antwort

4

Sie sind auf halbem Weg. Sie haben die richtigen zwei Änderungen am Code vornehmen:

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") 

Ersetzen $!filename mit $.filename in der File Klasse erzeugt eine öffentliche Accessor Methode (.filename) in dieser Klasse.

(Beachten Sie, dass Attribute zu einer Klasse technisch immer privat sind, also immer auf andere Klassen nicht zur Verfügung, auch trusted diejenigen. Wenn Sie den Begriff „public Attribut“ sehen wirklich bedeutet, es gibt eine „öffentliche Zugriffs“ ist, der den Zugriff steuert zu einem entsprechenden zugrundeen liegenden privaten Attribute.)

die ! twigil von der BUILD Signatur in der XmlFile Klasse Entfernen bedeutet, dass Sie nicht mehr sind versucht, ein nicht vorhandenes XmlFile Attribut zu verweisen und stattdessen nur ein benanntes Argument übergeben.

Per 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.

(Es ist das "public Attribut" falsche Bezeichnung Es bedeutet "Attribute mit einem passenden öffentlichen Accessor"..)

+0

In der Tat ja :) Danke. – Mikkel

0

Wenn Sie es privat bleiben möchten, können Sie füge es auch immer direkt zur Unterklasse hinzu. (Vielleicht kontrollieren Sie nicht die Klasse, die Sie unterklassifizieren?) Sie müssen natürlich vorsichtig sein, welche Methoden welche Dinge zwischen Ihrer Klasse und Unterklasse machen.

class File                                                          
{                                                            
    has $!filename;                                                
}                                                                                                                      

class XmlFile is File                                                       
{ 
    has $!filename; 

    submethod BUILD(:$!filename)                                                    
    { 
    } 
} 

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

Sie können auch zu prüfen, unter Verwendung eines ‚hat eine‘ Beziehung statt einer ‚ist eine‘ Beziehung durch ein Attribut class XmlFile machen, die eine class File hält je nachdem, was Sie zu tun versuchen.

Die Eigenschaft handles macht Delegierung in eine andere Klasse zu einer besonders einfachen und nützlichen Option zur direkten Unterklassenbildung.