有哪些语言支持Go的接口风格而无需显式声明?

5

我是一个有一定经验的业余程序员,对C++、D、Java、C#等语言很熟悉。

除了Go语言之外,几乎每一种语言都要求我明确声明我正在实现一个接口。这几乎是荒谬的,因为我们今天已经有像Haskell这样的语言的编译器,它可以使用非常少量的提示进行几乎全程序类型推断。

我正在寻找这样一种编程语言:

interface ITest {
    void Test();
}

class Test {
    void Test() { }
}

void main() {
    ITest x;
    x = new Test;
}

哪些语言会自动标记 Test 为实现了 ITest

预计时间: 我不是在寻找鸭子类型。我正在寻找具有推断的严格类型语言。


JavaScript算吗?您可以在具有Test()函数的任何对象上调用它,而无需声明接口。 - Denys Séguret
我不确定这个问题是否适合在SO上提问。如果你想要一个列出拥有Go语言这一神奇功能的语言列表,也许程序员交流社区会更好。 - Denys Séguret
1
你是否正在寻找使用鸭子类型的编程语言?比如JS、Python、Ruby等等? - Florian Margaine
请点击这里查看有关“鸭子类型”的相关内容。 - hatchet - done with SOverflow
@hatchet 鸭子类型是动态验证的,我猜测OP对静态验证的解决方案感兴趣。 - JaredPar
1
可能是 https://dev59.com/qXVC5IYBdhLWcg3wcwwm 的重复问题。 - hatchet - done with SOverflow
2个回答

12

D语言的标准库Phobos中拥有一个名为wrap的功能,可以完成您所需求的操作。以下是从该函数的单元测试中摘取的示例:

interface A {
  int run();
}

interface B {
  int stop();
  @property int status();
}

class X {
  int run() {
    return 1;
  }

  int stop() {
    return 2;
  }

  @property int status() {
    return 3;
  }
}

auto x = new X();

auto ab = x.wrap!(A, B);
A a = ab;
B b = ab;
assert(a.run() == 1);
assert(b.stop() == 2);
assert(b.status == 3);

这项工作将从v2.064版本开始提供,并且已经在git HEAD上。


1
这是拉取请求的链接 https://github.com/D-Programming-Language/phobos/pull/1265 - yaz
1
另外,如果您想要恢复原始的X,只需使用 ab.unwrap!X() - Sebastian Graf

0
几乎所有动态语言(如JavaScript、Python等)都支持这种模式。但我猜你对静态验证类型是否满足所需接口的语言更感兴趣。 C++ 尽管如此,这种支持并不完全符合您的要求,因为您不会直接使用ITest。相反,您将使用一个模板,该模板仅访问类型的所需成员。
// C# style solution 
void UseIt(ITest p) { 
  p.Test();
}

// C++ style solution
template <typename T>
void UseIt(T p) { 
  p.Test();
}

C++中的UseIt方法适用于任何具有可访问成员Test的类型。这里不需要接口。

class C1 { 
public: 
  void Test() { }
}

class C2 { } 

UseIt<C1>(C1());  // Ok
UseIt<C2>(C2());  // Error! 

TypeScript

TypeScript直接实现了您所描述的模式。归根结底,TypeScript只是JavaScript的一个薄包装器,因此具有动态性。但它确实提供了编译时类型注释。它对接口的支持完全符合您在问题中描述的模式。

F#

F#通过内联声明的成员约束具有类似于C++的支持。

let inline UseIt<^T when ^T : (member Test: unit -> unit)> s = ...

是的,D语言在这方面与C++相似。 - Adam D. Ruppe
@AdamD.Ruppe 我假设D是这样的,但是我对它的经验不足,无法对其进行明智的评论。 - JaredPar
这不完全是我想要的:一个模板/通用解决方案有(除非编译器非常聪明)几个关联的机器代码序列,而接口解决方案通常只有一个(取决于接口表查找)。 - Kile Kasmir Asmussen
@KarlDamgaardAsmussen C++模板将导致直接调用所需的方法。这应该始终比接口分派少指令。 - JaredPar
@BCS 是的,那是真的。不过这与Karl的论点不同,我想理解他的评论。 - JaredPar
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接