在给定的编程语言中,什么时候对象或其他东西被称为“一级”,为什么?它们与其他语言有什么不同?

当有人说“一切都是一个对象”(就像在Python中),他们真的意味着“一切都是一流的”吗?


当前回答

“一流”的意思是你可以用通常的方式操作它们。大多数时候,这只是意味着你可以将这些一级公民作为参数传递给函数,或者从函数返回它们。

这对于对象来说是不言自明的,但对于函数,甚至类来说并不总是如此明显:

void f(int n) { return n * 2; }

void g(Action<int> a, int n) { return a(n); }

// Now call g and pass f:

g(f, 10); // = 20

这是c#中的一个例子,其中函数实际上不是一级对象。因此,上面的代码使用了一个小的变通方法(即一个名为Action<>的泛型委托)来将函数作为参数传递。其他语言,如Ruby或Python,甚至允许将类和代码块视为普通变量(或者在Ruby的情况下,常量)。

其他回答

在我看来,这是自然语言中用来描述事物的隐喻之一。该术语本质上用于将函数描述为第一类对象的上下文中。

如果考虑面向对象语言,我们可以赋予对象各种特性,例如:继承、类定义、传递到其他代码段的能力(方法参数)、存储在数据结构中的能力等。如果我们可以对一个通常不被认为是对象的实体做同样的事情,就像java脚本中的函数一样,这样的实体被认为是第一类对象。

这里的第一类本质上是指不作为第二类处理(具有降级行为)。本质上,嘲讽是完美的或难以区分的。

“一流”的意思是你可以用通常的方式操作它们。大多数时候,这只是意味着你可以将这些一级公民作为参数传递给函数,或者从函数返回它们。

这对于对象来说是不言自明的,但对于函数,甚至类来说并不总是如此明显:

void f(int n) { return n * 2; }

void g(Action<int> a, int n) { return a(n); }

// Now call g and pass f:

g(f, 10); // = 20

这是c#中的一个例子,其中函数实际上不是一级对象。因此,上面的代码使用了一个小的变通方法(即一个名为Action<>的泛型委托)来将函数作为参数传递。其他语言,如Ruby或Python,甚至允许将类和代码块视为普通变量(或者在Ruby的情况下,常量)。

当一个人说“一切都是一个对象”(就像在Python中),他的意思真的是“一切都是一流的”吗?

Yes.

Python中的所有东西都是一个合适的对象。甚至是其他语言中的“基本类型”。

您会发现像2这样的对象实际上具有相当丰富和复杂的接口。

>>> dir(2)
['__abs__', '__add__', '__and__', '__class__', '__cmp__', '__coerce__', '__delattr__', '__div__', '__divmod__', '__doc__', '__float__', '__floordiv__', '__getattribute__', '__getnewargs__', '__hash__', '__hex__', '__index__', '__init__', '__int__', '__invert__', '__long__', '__lshift__', '__mod__', '__mul__', '__neg__', '__new__', '__nonzero__', '__oct__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdiv__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__str__', '__sub__', '__truediv__', '__xor__']

因为在Python中所有东西都是一级对象,所以有相对较少的模糊的特殊情况。

例如,在Java中,有一些基本类型(int, bool, double, char)不是正确的对象。这就是为什么Java必须引入Integer、Boolean、Double和Character作为第一类类型。这可能很难教给初学者——原始类型和类必须同时存在的原因并不明显。

这也意味着对象的类本身就是一个对象。这与c++不同,c++中的类在运行时并不总是具有独特的存在。

类型2是类型'int'对象,它有方法、属性和类型。

>>> type(2)
<class 'int'>

内置类型(如int)的类型是类型'type'对象。它也有方法和属性。

>>> type(type(2))
<class 'type'>

在《计算机程序的结构与解释》2A课(1986)的一张幻灯片上,引用了Christopher Stracey的话:

一等公民的权利和特权:

由变量命名。 作为参数传递给过程。 作为过程的值返回。 被合并到数据结构中

简而言之,这意味着对物体的使用没有限制。这和 任何其他物体。

第一类对象是一种实体,可以动态地创建、销毁、传递给函数、作为值返回,并具有编程语言中其他变量所具有的所有权限。

Depending on the language, this can imply: being expressible as an anonymous literal value being storable in variables being storable in data structures having an intrinsic identity (independent of any given name) being comparable for equality with other entities being passable as a parameter to a procedure/function being returnable as the result of a procedure/function being constructible at runtime being printable being readable being transmissible among distributed processes being storable outside running processes

源。

在c++中,函数本身并不是第一类对象,但是:

你可以重写'()'操作符,使它有可能有一个对象函数,这是第一类。 函数指针是第一流的。 Boost bind, lambda和function确实提供了第一类函数

在c++中,类不是第一类对象,而是这些类的实例。在Python中,类和对象都是第一类对象。(有关类作为对象的更多细节,请参阅这个答案)。

下面是Javascript第一类函数的例子:

// f: function that takes a number and returns a number
// deltaX: small positive number
// returns a function that is an approximate derivative of f
function makeDerivative( f, deltaX )
{
    var deriv = function(x)
    { 
       return ( f(x + deltaX) - f(x) )/ deltaX;
    }
    return deriv;
}
var cos = makeDerivative( Math.sin, 0.000001);
// cos(0)     ~> 1
// cos(pi/2)  ~> 0

源。

不是第一类对象的实体称为第二类对象。c++中的函数是第二类,因为它们不能动态创建。

关于编辑:

编辑。当一个人说“一切都是。 一个对象”(就像在Python中一样) 的确意味着“一切都是” 一流的”?

术语对象可以宽泛地使用,并不意味着是第一流的。将整个概念称为“第一类实体”可能更有意义。但是在Python中,他们的目标是使所有东西都是一流的。我相信对你说话的人的意图是一流的。