什么';smalltalk中的消息传递非常特别
我正在看Smalltalk的介绍。 在C++中,类内声明的函数可以由该类的对象调用,类似地在SimultTalk中,称为消息的关键字被写入对象的名称附近。 (不太清楚,但也想在此询问是否有一个独特的方法用于响应消息?) 基本上,在我天真的头脑中,这似乎只是语法风格的不同。但是,我想知道在编译或内存结构方面,这种调用上的差异是否有任何意义 提前谢谢 附言:我向你们所有人鞠躬,感谢你们的时间和回答。非常感谢。 你在C++中调用函数,因为在编译时你知道哪个函数被调用(或者至少你有一个在类层次结构中定义的函数集。什么';smalltalk中的消息传递非常特别,smalltalk,Smalltalk,我正在看Smalltalk的介绍。 在C++中,类内声明的函数可以由该类的对象调用,类似地在SimultTalk中,称为消息的关键字被写入对象的名称附近。 (不太清楚,但也想在此询问是否有一个独特的方法用于响应消息?) 基本上,在我天真的头脑中,这似乎只是语法风格的不同。但是,我想知道在编译或内存结构方面,这种调用上的差异是否有任何意义 提前谢谢 附言:我向你们所有人鞠躬,感谢你们的时间和回答。非常感谢。 你在C++中调用函数,因为在编译时你知道哪个函数被调用(或者至少你有一个在类层次结构中定义
Smalltalk是动态类型和后期绑定的,因此在编译期间,您不知道将对哪个方法进行求值(如果有)。因此,您发送一条消息,并且如果对象具有带有该选择器的方法,则对其进行求值。否则,“消息不可理解”出现异常。以下是一些在C中找不到的示例++ 在Smalltalk中,通过发送消息(发送到超类或名称空间,具体取决于方言)来创建一个新类 在Smalltalk中,通过向编译器发送消息来编译新方法 在Smalltalk中,通过发送消息打开调试器以响应未处理的异常。所有异常处理都是通过发送消息来实现的 在Smalltalk中,您可以查询类的方法,或者通过发送消息来收集其所有实例 更简单的是,所有控制结构(分支、循环等)都是通过发送消息来执行的
在Smalltalk中,消息的接收者完全可以控制消息的处理方式。它是一个真正的对象,而不是一个具有操作功能的数据结构
这意味着在SMALLATE中,可以向任何对象发送任何消息。编译器对它没有限制,它在运行时都被处理。在C++中,只能调用编译器知道的函数。
也可以说,SimalTalk消息只是符号(唯一字符串),不是C++中的函数地址。这意味着很容易通过交互方式或通过网络连接来发送消息。有一个<代码>执行:方法,它允许您发送一个给定字符串名的消息。
一个对象甚至接收到它没有实现的消息。虚拟机检测到这种情况,并创建一个
消息
对象,然后发送消息NotUnderstanding:
消息。同样,如何处理未知消息是对象的唯一责任。大多数对象只是继承默认的实现,而默认的实现是a表示有错误,但对象本身也可以处理。例如,它可以将这些消息转发到远程对象,或将它们记录到文件中,等等。这里已经有了很好的答案。让我添加一些详细信息(最初,这部分内容在注释中)
在普通C中,每个函数调用的目标在链接时被确定(除了使用函数指针)。C++添加虚拟函数,在运行时确定调用的实际函数(动态调度,后期绑定)。.函数指针在某种程度上允许自定义分派机制,但您必须自己编程
Behavior
是Class
的一个超类)有这样一个方法字典。正如@aka.nice在他的回答中指出的,可以查询方法字典。但是也可以添加(或删除)方法Smalltalk系统运行时。当Smalltalk VM发送消息时,它会在接收方超类链的方法字典中搜索正确的方法。通常会有缓存,以避免查找的重复成本
也注意到消息传递是SMALLATTS中对象通信的唯一方式。两个对象不能访问彼此的实例变量,即使它们属于同一类。在C++中,可以编写破坏此封装的代码。因此,消息发送在SimultTalk中是基本的,而C++中基本上是可选的特征。e
在C++、java和类似语言中,还有另一种调度形式,称为函数重载。它只在编译时发生,并且根据调用站点中声明的参数类型选择函数。在运行时,它不能影响它。SMALLATE显然不提供这种形式的调度,因为它没有。变量的静态类型。尽管如此,也可以使用习惯用法来实现,例如。其他语言,如Common Lisp的CLOS或Groovy,提供了更通用的多重分派,这意味着将根据所有参数的接收方类型和运行时类型来选择方法
*一些特殊消息,例如ifTrue:
ifFalse:whileTrue:
a