作者:wugege12 | 来源:互联网 | 2022-11-21 18:57
我有一个通用的接口来描述对输出流的访问,如下所示:
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> Gama11..:
抽象不能实现接口,因为它们是编译时功能,并且在运行时不存在。这与接口冲突,它们确实在运行时存在并且动态运行时检查像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;
}