6

我有兴趣学习一种在内部将对象处理为哈希表(如 JavaScript)但可以用强类型包装它们以在设计时提供代码完成/智能感知的好处的语言。以下是我希望这种梦幻语言发挥作用的方式:

public class Lion
{
  public void Roar() { Console.WriteLine("Aaarrgghh");}
} 

public static Main(string[] args)
{
  object myCat = new object(); // just plain object, no type!
  // adding a Roar() method to the myCat instance 
  myCat.Roar += delegate() {Console.WriteLine("Miauew");}
  // At this point myCat should qualify to be a Lion.
  // So we should be able to successfully duck-type-cast 
  // her to a lion
  Lion myLion = myCat as Lion;
  // now the myLion reference is strongly typed, 
  // so I expect the Intellisense window pop up 
  // and offer me the Roar() method when I hit the dot after "myLion"
  myLion.Roar();
}

我希望这个程序能够无误编译、无异常运行并在控制台上打印 “Miauew”。有没有一种语言可以做到这一点?也许是 C#4.0?

4

5 回答 5

3

也许是 C# 4.0 中的新动态类型。看看这个:http: //blogs.msdn.com/cburrows/archive/2008/10/27/c-dynamic.aspx

于 2009-06-28T13:38:45.943 回答
2

这取决于您让 Lion 类型实现非虚拟方法的目的。

扩展类型(给定类型的对象集合是那些具有类型属性的对象,这接近于鸭子类型的静态等价物)要求对象的结构暗示它的类型,但是你的 Lion type 没有结构——它只说任何是狮子的东西都有特定的 Roar 方法。因此,对于您的示例,我看不出您可以将猫变成狮子的任何方式,因为它不具有您所说的狮子所具有的唯一结构属性。

另一方面,如果您打算说您所说的任何内容是 Lion 可能有其自己的 Roar 方法或将在 Lion 中使用该方法,那么它并没有说明 Lions 的对象类型,并且 AFAIK 您可以获得对象上的扩展方法具有相同的行为(尽管我不知道足够的 C# 来知道 self 方法是否覆盖 C# 中的扩展方法)。

在动态 IDE 中,没有理由需要在 IDE 确定 myCat 具有 Roar 属性之前强制转换为 Lion - 该信息是静态可推断的。

IDE 支持在具有动态构造类型的语言(例如 JavaScript)中难以支持的原因是您可以这样做:

let myCat = {}

if ( locale.name == 'en' )
    myCat.roar = function () { alert ( "Miauew" ); }
else
    mCat[ resources.getString( 'roar' ) ] = 
        function () { alert ( resources.getString ( 'Miauew' ) ); }


// the structure of the type of myCat depends what locale the code
// is running in, so you can't deduce the Intellisense
myCat.

这种情况当然意味着如果没有更深入的分析(例如,检查您的法国猫是否总是被要求用法语咆哮),您也无法预测代码是否会工作。

如果 Intellisense 不能推断出结构可静态推断的对象的结构,那么这是 Intellisense 的弱点,而不是动态类型的弱点。

在您的示例中,您认为强类型的好处是什么?

于 2009-06-28T13:59:06.667 回答
2

每次我试图计划任何这样的事情时,问题都是演员阵容。当然,您可以只听程序员的话,但这结合了两种打字系统最糟糕的功能。也许演员可以在运行时检查一个对象是否实现了 Lion 接口,但这基本上是不可能的。在这种情况下,它看起来是合理的,因为您所需要的只是一个void (*)()函数的存在。但一般来说,如果 Lion 有一个getHabitat方法返回一个应该属于另一个接口的对象呢?强类型语言需要能够确定它确实如此,但如果不实际调用该方法,您通常无法判断无类型代码是否返回 Habitat,因此在强类型术语中您无法工作判断它是否是狮子。

所以我从来没有解决过这样的问题:当混合弱类型和强类型的代码部分时,你最终会得到强类型的代码,在任何时候都可能调用一个方法并取回一个没有实现接口的对象它应该。这不是强类型,而是带有误导性代码注释的动态类型。

于 2009-06-28T14:00:00.753 回答
1

这是一个有趣的想法,并且之前已经探索过。在我给你我的看法之后,我会链接到一些研究和现有的工作。我将讨论脚本语言和静态命令式语言,因为我认为这就是您所说的。

根本问题是类型在静态和动态类型系统中的含义不同。在动态系统中,类型是值的属性,并且随着值的传递,类型也是如此。在静态系统中,您可以限制变量(等)可能持有的值的类型。到目前为止,一切都很好。

动态语言中的静态类型

当您查看对象在脚本语言中的使用方式时,就会出现问题——它们都是鸭子类型的。这意味着类型的名称(nominal-typing)没有用。所有现代命令式语言(Java、C#、C++、C)都使用名义类型系统。所以在 C++ 中你可能会说你期望一个Duck.,但在 Python 中你真的想要一个quack().

所以考虑将静态类型添加到鸭子类型的语言中。由于函数会将参数扩展为quack(),但不能说它期望 a Duck,因此很难将两者结合起来。您可以定义一个名为quackswhich can的接口quack(),并将其用作类型。但这确实有点冗长,它扼杀了动态类型的好处。不过,也许有一些东西可以做到这一点(某种结构类型系统)。

另一种选择是只要求程序员指定Duck,并且无论如何都该死这个鸭子打字业务-没有人真正使用它吗?但是你只是在用 Python 编写 Java,作为曾经尝试过的人,让我告诉你它会适得其反。

静态语言中的动态类型

所以让我们换个角度看。dynamicC# 将如何从关键字中受益?简单的答案是它不会。老实说,我没有看到你从 C# 中的 Python 获得的任何美丽和自由dynamic。现在,我对它的唯一了解来自 Jon Skeet 的一次演讲,但我得到的压倒性印象是它冗长而不优雅。而且我认为这不是 C# 人员的实现错误。我认为这是因为动态类型在 Python 中解决的问题已经在 C# 中解决了(尽管很冗长),并且dynamic没有给聚会带来任何好处。

研究静态/动态的东西

查看Jeremy Siek 的渐进式打字资料,它是关于目前最先进的静态/动态研究的。虽然有点难读,而且我自己只是粗略地看了一眼,所以我无法总结它。不过,单看他的相关作品还是挺有意思的,STOP会议应该会有好东西。

于 2009-09-02T14:04:52.870 回答
0

与您的示例不密切相关,但 Scala 的隐式转换是一种经过深思熟虑(尽管有时难以遵循)的机制,可以以完全受控、静态检查的方式扩展类的功能。

此外,结构类型有时可以用作以类型安全的方式替代鸭子类型。

于 2011-08-12T23:33:52.747 回答