2016-08-04 9 views
0

У меня есть интерфейс, который выглядит так.Как написать общий тип функции

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

Поскольку существует только один метод, я хочу написать класс, который преобразует замыкание в экземпляр Value.

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); 
    } 
} 

Однако <T> в типе function<T>(ValueVisitor<T>): T является синтаксической ошибкой. Независимо от того, где я положил <T>, он не будет анализировать.

Как я могу написать это в Hack?

+0

Простите мое отсутствие воображения, но что ваше общее закрытие '$ f' даже сделать, так как он не может захватить' T' типизированных значений из его окружения? Как это полезно для использования с ValueVisitor '? – concat

+0

'ValueVisitor ' имеет методы, которые возвращают 'T', поэтому функция '(функция (ValueVisitor ): T)' должен возвращать 'T', и единственное, что он должен сделать, это вызвать методы 'ValueVisitor ', предоставленный ему. – Jesse

+0

Мне любопытно, сколько разных комбинаций вызовов методов вы намереваетесь делать на 'ValueVisitor', но в целом это кажется разумным. Ваш лучший выбор - это, вероятно, запрос на функцию команды Hack. (Лично я тоже надеюсь, что анонимные классы в конечном итоге будут реализованы, что тоже может помочь вам здесь) – concat

ответ

-1

Прямо сейчас я не могу попробовать, если его работы, но это может работает:

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' станет значением, которое может принимать только посетители, производящие значения типа' T' (по построению), а метод 'accept' больше не является общим и поэтому несовместим с методом' accept' 'Value' , – Jesse

-1

Его работает для меня хорошо ...

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

Это не то, как работают посетители. 'ValueVisitor ' не означает посетителя для значений типа 'T', это означает, что посетитель производит значение типа' T'. Тип посещенных значений - это параметры для методов ValueVisitor, а не 'T'. Вы можете прочитать о шаблоне посетителя здесь: https://en.wikipedia.org/wiki/Visitor_pattern – Jesse

+0

Вы запросили помощь для синтаксической ошибки, поэтому мой ответ предназначен только для разрешения вашей синтаксической ошибки. И все же он решает ... –

+0

Исправление ошибки синтаксиса путем замены его кодом, который не работает, не помогает. – Jesse