2016-08-04 10 views
0

Ich habe eine Schnittstelle, die so aussieht.Wie generische Funktion schreiben

interface Value { 
    public function accept<T>(ValueVisitor<T> $visitor): T; 
} 

Da es nur eine Methode ist, möchte ich eine Klasse schreiben, die einen Verschluss in eine Instanz von Value umwandelt.

final class ClosureValue implements Value { 
    public function __construct(
    private (function<T>(ValueVisitor<T>): T) $f 
) {} 

    public function accept<T>(ValueVisitor<T> $visitor): T { 
    $f = $this->f; 
    return $f($visitor); 
    } 
} 

jedoch die <T> in der Art function<T>(ValueVisitor<T>): T ist ein Syntaxfehler. Egal wo ich die <T> setze, wird es nicht analysieren.

Wie kann ich das in Hack schreiben?

+0

Verzeihen Sie meinen Mangel an Vorstellungskraft, aber was kann Ihre generische Schließung '$ f' sogar tun, da es' T'-typisierte Werte von seiner Umgebung nicht erfassen kann? Wie interagiert es sinnvollerweise mit ValueVisitor ? – concat

+0

'ValueVisitor ' hat Methoden, die 'T's zurückgeben, so eine Funktion' (Funktion (ValueVisitor ):) muss ein 'T' zurückgeben und das einzige Mittel, das es zu tun hat, ist, Methoden des zu benennen 'ValueVisitor ' gegeben. – Jesse

+0

Ich bin gespannt, wie viele verschiedene Kombinationen von Methodenaufrufen Sie auf "ValueVisitor" machen möchten, aber im Allgemeinen erscheint das vernünftig. Ihre beste Wette ist wahrscheinlich eine Feature-Anfrage an das Hack-Team. (Persönlich hoffe ich auch, dass anonyme Klassen eventuell implementiert werden, was Ihnen auch hier helfen könnte) – concat

Antwort

-1

Im Moment kann ich nicht versuchen, wenn seine Arbeits aber diese Macht funktioniert:

final class ClosureValue<T> implements Value { 
    public function __construct(
     private (function(ValueVisitor<T>) : T) $myF 
    ) { 

    } 


    public function accept(ValueVisitor<T> $visitor) : T { 
     $fn = $this->myF; 
     return $fn($visitor); 
    } 
} 
+0

'ClosureValue' würde zu einem Wert werden, der nur Besucher akzeptiert, die Werte vom Typ' T' produzieren (entschieden für die Konstruktion), und die 'accept'-Methode ist nicht länger generisch und daher mit der' accept'-Methode von 'Value' nicht kompatibel . – Jesse

-1

Sein für mich gut funktioniert ...

classes.hh

<?hh // strict 

class ValueVisitor<T> 
{ 
    protected T $value; 
    public function __construct(T $new) { $this->value = $new; } 
    public function get(): T { return $this->value; } 
} 

interface Value { public function accept<T>(ValueVisitor<T> $visitor): T; } 

final class ClosureValue<T> implements Value { 
    public function __construct(
    private (function(ValueVisitor<T>) : T) $myF 
) { 

} 

public function accept(ValueVisitor<T> $visitor) : T { 
    $fn = $this->myF; 
    return $fn($visitor); 
} 

// main.hh

<?hh // strict 

class MyClass 
{ 
    public function __construct(
     protected string $myVal 
    ) { } 

    public function getMyVal(): string { return $this->myVal; } 
} 

function main<T>() : void 
{ 
    $visitor = new ValueVisitor(12); 
    $val = new ClosureValue(function(ValueVisitor<int> $f): int { 
     return $f->get(); 
    }); 

    echo $val->accept($visitor); 


    $visitor2 = new ValueVisitor('Foo'); 
    $val2 = new ClosureValue(function(ValueVisitor<string> $f): string { 
     return $f->get(); 
    }); 

    echo $val2->accept($visitor2); 

    $visitor3 = new ValueVisitor(new MyClass("asd")); 
    $val3 = new ClosureValue(function(ValueVisitor<MyClass> $f): MyClass { 
     return $f->get(); 
    }); 

    print_r($val3->accept($visitor2)); 
} 

i ndex.hh

<?hh // partial  

require 'classes.hh'; 
require 'helpers.hh'; 
require 'main.hh'; 

main(); 
+0

So arbeiten die Besucher nicht. 'ValueVisitor ' bedeutet keinen Besucher für Werte vom Typ 'T', es bedeutet, dass ein Besucher einen Wert vom Typ' T' erzeugt. Die Art der Werte, die besucht werden, sind die Parameter zu den Methoden von "ValueVisitor", nicht "T". Sie können über das Besuchermuster hier lesen: https://en.wikipedia.org/wiki/Visitor_pattern – Jesse

+0

Sie haben Hilfe für Syntaxfehler gefragt, so ist meine Antwort nur für das Lösen Ihres Syntaxfehlers. Und doch löst es ... –

+0

Es ist nicht hilfreich, einen Syntaxfehler zu beheben, indem Sie ihn durch Code ersetzen, der nicht funktioniert. – Jesse

Verwandte Themen