在你看来,你遇到过的最令人惊讶、最怪异、最奇怪或最“WTF”的语言特性是什么?

请每个回答只回答一个特征。


当前回答

在我看来,这在c++中是不允许的:

class A {
public:
  virtual string foo(){return "A::foo";}
};

class B : public A {
public:
  virtual string foo(){return "B::foo";}
};

int main () {
  B* b = new B();
  // In my opinion the following should not be allowed
  cout << b->A::foo() << endl;  // Will print "A::foo"
}

这似乎是正确的,但这意味着如果不允许子类的用户调用原始方法而不是新方法,就不能重写方法。

只要考虑一个集合的子类,当向集合本身添加一个元素时,您希望增加元素的数量。

一个合乎逻辑的解决方案是重写add()方法,在添加元素之前增加计数器,但是新集合的用户可以使用旧方法向其添加元素,这样就绕过了增量,导致元素计数器与集合的实际元素数量不一致。

这在Java中是不可能的。

其他回答

好吧,这也是我最喜欢的很难找到的虫子…将以0开头的整数视为八进制数。这导致了一个只会在早上8点到10点之间显示的错误:

有一次,我帮助构建了一个自动回归测试,在晚上通过cron执行。在一个20人的团队中,它几乎适用于每个人——除了一个开发人员偶尔会抱怨自动测试失败,但当手动运行时,一切都很好。这甚至一次都无法人工复制。

好吧,原因是,我们根据date命令的输出进行了一些统计计算(在bash中),这只在早上8:00到9:59期间失败,因为我们将小时值读取为“08”(这是一个非法的八进制值,而“01”-“07”是有效的八进制值,从“10”开始,所有内容都被再次视为十进制)……

Scheme中没有保留标识符。因此,下面的表达式的值为1:

((lambda (lambda) lambda) (let ((let 1)) let))

注意,给定作用域内的定义是有限制的:任何定义都不能重新定义用于在该作用域内定义标识符的标识符,因此下面是一个语法错误:

(begin (define define 1) define)

Processing (processing.org)是一种基于Java的语言。简单来说,处理编译器是将特定于处理的语法转换为Java的Java预处理器。

由于语言的设计,它有一些惊喜:

Processing的类被编译成Java内部类,这会引起一些麻烦,比如私有变量并不是真正私有的

class Foo {
  private int var = 0; // compiles fine
}

void setup() {
  Foo f = new Foo();
  print(f.var); // but does not causes compile error
}

同样缺少draw()函数会导致事件处理程序不被调用:

// void draw() {} // if you forgot to include this
void mousePressed() {
  print("this is never called");
}

Javascript中的变量/函数声明:

var x = 1;
function weird(){
  return x;
  var x = 2;
}

Weird()返回undefined…即使任务从未发生,X也被“占用”了。

类似的,但也不是那么出乎意料

function weird2(){
   var x;
   return x();
   function x(){ return 2 };
}

返回2。

不知道这是不是一个功能。对一些人来说,是的,但对另一些人来说,这可能是一种令人讨厌的行为。不管怎样,我认为这是值得一提的。

在Python中,内置函数round()在Python 2x和Python 3x之间的行为略有不同。

对于Py 2x,

>>> round(0.4)
0.0
>>> round(0.5)
1.0
>>> round(0.51)
1.0
>>> round(1.5)
2.0

对于Py 3x,

>>> round(0.4)
0
>>> round(0.5)
0
>>> round(0.51)
1
>>> round(1.5)
2

我只是不熟悉Py 3x中的round()与0的工作方式。

Py 2x和Py 3x中round()的文档。