Как абстрактный может реализовать интерфейс? - PullRequest
0 голосов
/ 10 января 2019

У меня есть общий интерфейс, который описывает доступ к выходному потоку так:

interface IOutput {
    function writeInteger(aValue:Int):Void;
}

И у меня есть абстрактная реализация этого интерфейса, основанная на стандартном haxe.io.BytesOutput классе:

abstract COutput(BytesOutput) from BytesOutput {
    public inline function new(aData:BytesOutput) {
        this = aData;
    }
    public inline function writeInteger(aValue:Int):Void {
        this.writeInt32(aValue);
    }
}

Хотя этот реферат действительно реализует интерфейс, описанный выше, нет прямой ссылки на интерфейс, и когда я пытаюсь использовать его следующим образом:

class Main {
    public static function out(aOutput:IOutput) {
        aOutput.writeInteger(0);
    }
    public static function main() {
        var output:COutput = new BytesOutput();
        out(output); // type error
    }
}

Компилятор выдает ошибку: COutput should be IOutput. Я могу решить эту проблему только с помощью общего класса, который упаковывает BytesOutput и реализует IOutput.

У меня вопрос, как показать компилятору Haxe, что реферат реализует интерфейс.

1 Ответ

0 голосов
/ 10 января 2019

Тезисы не могут реализовать интерфейсы , потому что они являются функцией времени компиляции и не существуют во время выполнения. Это противоречит интерфейсам, они do существуют во время выполнения, и динамические проверки во время выполнения, такие как Std.is(something, IOutput), должны работать.

Haxe также имеет механизм, называемый структурный подтип , который можно использовать в качестве альтернативы интерфейсам. При таком подходе нет необходимости в явном объявлении implements, достаточно, если что-то объединяет со структурой:

typedef IOutput = {
    function writeInteger(aValue:Int):Void;
}

К сожалению, аннотации не совместимы со структурным подтипом из-за способа их реализации.


Рассматривали ли вы вместо этого статические расширения ? По крайней мере, для вашего простого примера это выглядит как идеальное решение для создания метода writeInteger(), доступного для любого haxe.io.Output:

import haxe.io.Output;
import haxe.io.BytesOutput;
using Main.OutputExtensions;

class Main {
    static function main() {
        var output = new BytesOutput();
        output.writeInteger(0);
    }
}

class OutputExtensions {
    public static function writeInteger(output:Output, value:Int):Void {
        output.writeInt32(value);
    }
}

Вы можете даже объединить это со структурным подтипом, так что writeInteger() станет доступным для всего, что имеет метод writeInt32() ( try.haxe link ):

typedef Int32Writable = {
    function writeInt32(value:Int):Void;
}
...