哪些语言允许更改对象的身份(不强制转换)?

发布于 2024-11-06 18:06:57 字数 252 浏览 5 评论 0 原文

这篇文章中,一位勇敢的人希望(在 C++ 中)将 Base 类型的对象向下转换为派生 类型。假设 Derived 类型的属性不超过 Base,如果您嫉妒 Derived 类的额外方法,那么它可以有意义提供。

是否有编程语言允许这样的事情?

In this post, a brave wants (in C++) to downcast a object of type Base to a Derived type. Assuming that the Derived type has no more attributes than Base, it can make sense if you're jealous of the extra methods that the Derived class provides.

Are there programming languages that allow such a thing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

雨巷深深 2024-11-13 18:06:57

实际上,这在 Common Lisp 以及移植了 CLOS(Common Lis 对象系统)的其他 Lisp 方言中是没有问题的。您使用 change-class 通用函数为此。

CLOS 使用多个调度方法,因此方法不依赖于类或对象,它只是在一组与其参数的类型(或标识)类似的函数中选择的函数。使用 change-class 时,您可以像创建新实例一样给出参数,并且已存储在对象中的数据将保留。下面是一个小会话,展示了它是如何工作的:

CL-USER> (defclass base ()
       ((name :initarg :name)))
#<STANDARD-CLASS BASE>
CL-USER> (defclass derived (base)
       ((age :initarg :age :initform 0)))
#<STANDARD-CLASS DERIVED>
CL-USER> (defvar foo (make-instance 'base :name "John Doe"))
FOO
CL-USER> (change-class foo 'derived :age 27)
#<DERIVED {100338F2D1}>
CL-USER> (with-slots (name age) foo
       (list name age))
("John Doe" 27)
CL-USER> (defvar bar (make-instance 'base :name "Baby Joe"))
BAR
CL-USER> (change-class bar 'derived)
#<DERIVED {10036CF6E1}>
CL-USER> (with-slots (name age) bar
       (list name age))
("Baby Joe" 0)
CL-USER> 

如果这个默认行为还不够,您可以在 更新不同类的实例

是的,有一些编程语言允许这样的事情

Actually, this is something that is done without problem in Common Lisp, and in other Lisp dialects where CLOS (Common Lis Object System) was ported. You use the change-class generic function for that.

CLOS works with multiple dispatch methods, so a method is not tied to a class or object, it's just a function that is chosen in a group of similar functions WRT to the types (or identities) of its arguments. When using change-class, you can give arguments as if you were creating a new instance, and data already stored in the object will remain. Here is a little session that shows how it works:

CL-USER> (defclass base ()
       ((name :initarg :name)))
#<STANDARD-CLASS BASE>
CL-USER> (defclass derived (base)
       ((age :initarg :age :initform 0)))
#<STANDARD-CLASS DERIVED>
CL-USER> (defvar foo (make-instance 'base :name "John Doe"))
FOO
CL-USER> (change-class foo 'derived :age 27)
#<DERIVED {100338F2D1}>
CL-USER> (with-slots (name age) foo
       (list name age))
("John Doe" 27)
CL-USER> (defvar bar (make-instance 'base :name "Baby Joe"))
BAR
CL-USER> (change-class bar 'derived)
#<DERIVED {10036CF6E1}>
CL-USER> (with-slots (name age) bar
       (list name age))
("Baby Joe" 0)
CL-USER> 

If this default behaviour is not enough, you may define a method on update-instance-for-different-class.

So yeah, there are programming languages that allow such a thing!

ι不睡觉的鱼゛ 2024-11-13 18:06:57

不,但首先这样做就有很强烈的代码味道。

更好的替代方法是使用 装饰器模式,这正是它的用途。

No, but it's a strong code smell to do that in the first place.

A way better alternative is to use the decorator pattern, this is exactly what it was made to do.

怪我太投入 2024-11-13 18:06:57

如果 Derived 未添加任何属性,则它添加的方法必须在从 Base 获取的状态上运行。在这种情况下,为什么不将这些方法移至它们所属的 Base 位置呢?

If Derived adds no attributes then the method it adds must operate on state that it gets from Base. In that case, why not just move those methods to Base where they belong?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文