我可以在宣布成员时指定界面?

在考虑了这个问题一段时间之后,我发现静态鸭式语言可能确实有效。为什么在编译时不能将预定义的类绑定到接口?例如:

public interface IMyInterface
{
  public void MyMethod();
}

public class MyClass  //Does not explicitly implement IMyInterface
{
  public void MyMethod()  //But contains a compatible method definition
  {
    Console.WriteLine("Hello, world!");
  }
}

...

public void CallMyMethod(IMyInterface m)
{
  m.MyMethod();
}

...

MyClass obj = new MyClass();
CallMyMethod(obj);     // Automatically recognize that MyClass "fits" 
                       // MyInterface, and force a type-cast.

您知道支持此功能的任何语言吗?它会在Java或C#中有用吗?它在某种程度上存在根本缺陷吗?我知道你可以继承MyClass并实现接口或使用Adapter设计模式来完成同样的事情,但这些方法看似不必要的样板代码。

有帮助吗?

解决方案

静态类型语言,根据定义,在编译时检查类型,而不是运行时。上述系统的一个明显问题是编译器将在编译程序时检查类型,而不是在运行时。

现在,您可以在编译器中构建更多智能,以便派生类型,而不是让程序员明确声明类型;编译器可能会看到MyClass实现MyMethod()方法,并相应地处理这种情况,没有需要显式声明接口(如你所建议的那样)。这样的编译器可以使用类型推断,例如 Hindley-Milner

当然,像Haskell这样的静态类型语言已经按照你的建议做了类似的; Haskell编译器能够推断类型(大多数时候)而无需显式声明它们。但显然,Java / C#没有这种能力。

其他提示

这个问题的全新答案, Go正是这个功能。我认为这真的很酷<!> amp;聪明(虽然我有兴趣看看它在现实生活中是如何发挥作用的)并且在想到它时会感到荣幸。

正如在官方文档中所述(作为Tour of Go的一部分,带有示例代码)

  

接口是隐式实现的

     

类型通过实现其方法来实现接口。有   没有明确的意图声明,没有<!> quot; implements <!> quot;关键字。

     

隐式接口将接口的定义与其分离   实现,然后可以出现在没有的任何包中   预先安排。

如何在C ++中使用模板?

class IMyInterface  // Inheritance from this is optional
{
public:
  virtual void MyMethod() = 0;
}

class MyClass  // Does not explicitly implement IMyInterface
{
public:
  void MyMethod()  // But contains a compatible method definition
  {
    std::cout << "Hello, world!" "\n";
  }
}

template<typename MyInterface>
void CallMyMethod(MyInterface& m)
{
  m.MyMethod();  // instantiation succeeds iff MyInterface has MyMethod
}

MyClass obj;
CallMyMethod(obj);     // Automatically generate code with MyClass as 
                       // MyInterface

我实际上并没有编译这段代码,但我相信它是可行的,并且是原始提议(但非工作)代码的一个非常简单的C ++化。

我没有看到这一点。为什么不明确该类实现接口并完成它?实现接口是告诉其他程序员该类应该以接口定义的方式运行的原因。简单地在方法上具有相同的名称和签名并不能保证设计者的意图是使用该方法执行类似的操作。这可能是,但为什么要留下来解释(和误用)?

你可以<!>“离开<!>”的原因成功地使用动态语言与TDD有关,而不是与语言本身有关。在我看来,如果该语言提供了向使用/查看代码的其他人提供这些指导的工具,那么您应该使用它。它实际上提高了清晰度,值得一些额外的角色。如果您无权执行此操作,则适配器的用途与明确声明接口与其他类的关联方式相同。

ML系列中的大多数语言都支持带有推理和约束类型方案的结构类型,这是一种令人讨厌的语言设计术语,似乎很可能是短语<!>的含义; static duck-typing <!> quot;在最初的问题中。

这个家庭中更受欢迎的语言包括:Haskell,Objective Caml,F#和Scala。当然,与你的例子最匹配的那个是Objective Caml。以下是您的示例的翻译:

open Printf

class type iMyInterface = object
  method myMethod: unit
end

class myClass = object
  method myMethod = printf "Hello, world!"
end

let callMyMethod: #iMyInterface -> unit = fun m -> m#myMethod

let myClass = new myClass

callMyMethod myClass

注意:您使用的某些名称必须更改为符合OCaml的标识符案例语义概念,否则,这是一个非常直接的翻译。

另外值得注意的是,callMyMethod函数中的类型注释和iMyInterface类类型的定义都不是必需的。目标Caml可以在没有任何类型声明的情况下推断示例中的所有内容。

TypeScript!

好吧,好吧......所以它是一个javascript超集,可能不构成<!>“语言<!>”;但是这种静态鸭子输入在TypeScript中至关重要。

Boo绝对是一种静态鸭式语言: http://boo.codehaus.org/Duck +键入

摘录:

  

Boo是一种静态类型语言,   像Java或C#。这意味着你的嘘声   应用程序将以尽可能快的速度运行   用其他静态类型编码的那些   .NET或Mono的语言。但是使用   有时是一种静态类型的语言   把你限制在一个不灵活的地方   详细的编码风格,随着   有时必要的类型声明   (比如<!> quot; x as int <!> quot;,但事实并非如此   由于boo的类型通常是必要的   推论)有时是必要的   类型转换(请参阅转换类型)。嘘的   支持类型推断和   最终仿制药在这里有所帮助,但是......

     

有时放弃是合适的   静电提供的安全网   打字。也许你只是想探索   一个API而不用担心太多   方法签名或者你也许   创建与外部对话的代码   COM对象等组件。或   选择应该是你的选择   矿。

     

与普通类型一样   object,int,string ... boo有一个   特殊类型称为<!>“; duck <!>”;术语   灵感来自红宝石编程   语言的鸭子打字功能(<!> quot;如果它   像鸭子一样走路,像傻瓜一样嘎嘎叫   鸭子,它必须是鸭子<!>“;”。

新版本的C ++朝着静态鸭子打字的方向发展。你可以在某一天(今天?)写下这样的东西:

auto plus(auto x, auto y){
    return x+y;
}

如果x+y没有匹配的函数调用,它将无法编译。

至于你的批评:

  

一个新的<!>“CallMyMethod <!>”;是为您传递给它的每种不同类型创建的,因此它不是真正的类型推断。

但它是类型推断(你可以说foo(bar)其中foo是一个模板化函数),并且具有相同的效果,除了它更节省时间并且在编译代码中占用更多空间。

否则,您必须在运行时查找该方法。您必须找到一个名称,然后检查该名称是否具有使用正确参数的方法。

或者您必须存储有关匹配接口的所有信息,并查看与接口匹配的每个类,然后自动添加该接口。

在任何一种情况下,这都允许您隐式地和意外地破坏类层次结构,这对于新功能是不利的,因为它违背了C#/ Java的程序员习惯的习惯。使用C ++模板,您已经知道自己在雷区(并且他们还添加了功能(<!> quot; concepts <!> quot;)以允许对模板参数进行限制)。

Scala中的结构类型做了类似的事情。

参见静态检查<!>#8220;鸭子打字<!>#8221;在斯卡拉

Visual Basic 9的预发布设计支持使用动态接口进行静态鸭子类型,但是它们削减了功能 * 以便按时发货。

D( http://dlang.org )是一种静态编译的语言,通过wrap()提供duck-typing和unwrap()( http://dlang.org/phobos-prerelease/std_typecons.html #.unwrap )。

Crystal 是一种静态鸭式语言。 示例

def add(x, y)
  x + y
end

add(true, false)

add的调用导致此编译错误:

Error in foo.cr:6: instantiating 'add(Bool, Bool)'

add(true, false)
^~~

in foo.cr:2: undefined method '+' for Bool

  x + y
    ^

在我的编程语言 Heron 的最新版本中,它通过结构 - 子类型强制支持类似的东西运营商名为as。所以而不是:

MyClass obj = new MyClass();
CallMyMethod(obj);

你会写:

MyClass obj = new MyClass();
CallMyMethod(obj as IMyInterface);

就像在您的示例中一样,在这种情况下,MyClass不必显式实现IMyInterface,但如果它确实可以隐式发生转换,则可以省略<=>运算符。

我在

scroll top