什么';smalltalk中的消息传递非常特别

什么';smalltalk中的消息传递非常特别,smalltalk,Smalltalk,我正在看Smalltalk的介绍。 在C++中,类内声明的函数可以由该类的对象调用,类似地在SimultTalk中,称为消息的关键字被写入对象的名称附近。 (不太清楚,但也想在此询问是否有一个独特的方法用于响应消息?) 基本上,在我天真的头脑中,这似乎只是语法风格的不同。但是,我想知道在编译或内存结构方面,这种调用上的差异是否有任何意义 提前谢谢 附言:我向你们所有人鞠躬,感谢你们的时间和回答。非常感谢。 你在C++中调用函数,因为在编译时你知道哪个函数被调用(或者至少你有一个在类层次结构中定义

我正在看Smalltalk的介绍。 在C++中,类内声明的函数可以由该类的对象调用,类似地在SimultTalk中,称为消息的关键字被写入对象的名称附近。 (不太清楚,但也想在此询问是否有一个独特的方法用于响应消息?)

基本上,在我天真的头脑中,这似乎只是语法风格的不同。但是,我想知道在编译或内存结构方面,这种调用上的差异是否有任何意义

提前谢谢

附言:我向你们所有人鞠躬,感谢你们的时间和回答。非常感谢。

你在C++中调用函数,因为在编译时你知道哪个函数被调用(或者至少你有一个在类层次结构中定义的函数集。


Smalltalk是动态类型和后期绑定的,因此在编译期间,您不知道将对哪个方法进行求值(如果有)。因此,您发送一条消息,并且如果对象具有带有该选择器的方法,则对其进行求值。否则,“消息不可理解”出现异常。

以下是一些在C中找不到的示例++

在Smalltalk中,通过发送消息(发送到超类或名称空间,具体取决于方言)来创建一个新类

在Smalltalk中,通过向编译器发送消息来编译新方法

在Smalltalk中,通过发送消息打开调试器以响应未处理的异常。所有异常处理都是通过发送消息来实现的

在Smalltalk中,您可以查询类的方法,或者通过发送消息来收集其所有实例

更简单的是,所有控制结构(分支、循环等)都是通过发送消息来执行的


在Smalltalk中,消息的接收者完全可以控制消息的处理方式。它是一个真正的对象,而不是一个具有操作功能的数据结构

这意味着在SMALLATE中,可以向任何对象发送任何消息。编译器对它没有限制,它在运行时都被处理。在C++中,只能调用编译器知道的函数。

也可以说,SimalTalk消息只是符号(唯一字符串),不是C++中的函数地址。这意味着很容易通过交互方式或通过网络连接来发送消息。有一个<代码>执行:方法,它允许您发送一个给定字符串名的消息。


一个对象甚至接收到它没有实现的消息。虚拟机检测到这种情况,并创建一个
消息
对象,然后发送
消息NotUnderstanding:
消息。同样,如何处理未知消息是对象的唯一责任。大多数对象只是继承默认的实现,而默认的实现是a表示有错误,但对象本身也可以处理。例如,它可以将这些消息转发到远程对象,或将它们记录到文件中,等等。

这里已经有了很好的答案。让我添加一些详细信息(最初,这部分内容在注释中)

在普通C中,每个函数调用的目标在链接时被确定(除了使用函数指针)。C++添加虚拟函数,在运行时确定调用的实际函数(动态调度,后期绑定)。.函数指针在某种程度上允许自定义分派机制,但您必须自己编程

在SMALLATE中,所有消息发送都是动态调度的。在C++中,这大致意味着:所有成员函数都是虚拟的,没有独立的函数(总是有一个接收器)。。因此,Smalltalk编译器从不*决定消息发送将调用哪个方法。相反,被调用的方法在运行时由实现Smalltalk的虚拟机确定

<> P>一种实现虚拟函数调度的方法是虚函数表,SimultSalk中的近似等价是方法字典,但是,这些字典是可变的,不同于典型的虚函数表,它们是由C++编译器生成的,在运行时不改变。(
Behavior
Class
的一个超类)有这样一个方法字典。正如@aka.nice在他的回答中指出的,可以查询方法字典。但是也可以添加(或删除)方法Smalltalk系统运行时。当Smalltalk VM发送消息时,它会在接收方超类链的方法字典中搜索正确的方法。通常会有缓存,以避免查找的重复成本

也注意到消息传递是SMALLATTS中对象通信的唯一方式。两个对象不能访问彼此的实例变量,即使它们属于同一类。在C++中,可以编写破坏此封装的代码。因此,消息发送在SimultTalk中是基本的,而C++中基本上是可选的特征。e

在C++、java和类似语言中,还有另一种调度形式,称为函数重载。它只在编译时发生,并且根据调用站点中声明的参数类型选择函数。在运行时,它不能影响它。SMALLATE显然不提供这种形式的调度,因为它没有。变量的静态类型。尽管如此,也可以使用习惯用法来实现,例如。其他语言,如Common Lisp的CLOS或Groovy,提供了更通用的多重分派,这意味着将根据所有参数的接收方类型和运行时类型来选择方法

*一些特殊消息,例如
ifTrue:
ifFalse:
whileTrue:
a