你怎么称呼改变其类的对象的方法?

时间:2009-03-25 19:31:44

标签: oop

假设您有一个Person对象,并且它上面有一个方法promote(),可以将其转换为Captain个对象。你怎么称呼这种方法/互动?

它也感觉像是反转:

myCaptain = new Captain(myPerson);

修改:感谢所有回复。我遇到这种模式的原因(在Perl中,但在任何地方相关)纯粹是为了方便。在不知道任何实现交易的情况下,您可以说Captain类“有一个”Person(我意识到这可能不是最好的例子,但请确保它不是子类)。

我假设的实施:

// this definition only matches example A
Person.promote() {
  return new Captain(this)
}

personable = new Person;

// A. this is what i'm actually coding
myCaptain = personable.promote();

// B. this is what my original post was implying
personable.promote(); // is magically now a captain?

因此,从字面上看,它只是构建Captain的便捷方法。我只是想知道这种模式是否在野外被看到并且它是否有名字。而且我猜是的,它并没有真正改变课程,因为它返回了另一个课程。但它理论上可以,因为我并不真正关心原作。

Ken ++,我喜欢你指出一个用例。有时改变某些东西真的很棒,比如一个对记忆敏感的环境。

5 个答案:

答案 0 :(得分:5)

对象的方法不应更改其类。您应该拥有一个返回新实例的成员:

myCaptain = myPerson->ToCaptain();

或者使用构造函数,如示例所示:

myCaptain = new Captain(myPerson);

我将其称为转换,甚至是转换,具体取决于您如何使用该对象。如果您有一个值对象:

Person person;

您可以使用构造函数方法隐式转换:

Captain captain = person;

(假设是C ++。)

答案 1 :(得分:5)

更简单的解决方案可能是将排名作为人的财产。我不知道您的数据结构或要求,但如果您需要尝试打破语言基础知识,可能会有更好的方法。

答案 2 :(得分:3)

您可能想要考虑“状态模式”,有时也称为“状态对象”模式。它在“设计模式”一书中定义,但您可以在Google上轻松找到很多相关信息。

模式的一个特征是“对象似乎会改变它的类。”

以下是一些链接:

Objects for States

Pattern: State

答案 3 :(得分:1)

每个人似乎都在假设一个类似C ++ / Java的对象系统,可能是因为问题中使用了语法,但很有可能在运行时用其他语言更改实例的类。

Lisp的CLOS允许随时更改实例的类,这是一个定义明确且高效的转换。 (术语和结构略有不同:方法不属于CLOS中的类。)

但是,我从未听说过这种特定类型的转型的名称。执行此操作的功能简称为change-class

理查德·加布里埃尔seems to call it之后的“变更类协议”,在Kiczales'AMOP之后,它正式化为CLOS内部许多元协议的“协议”。

人们想知道你为什么要这样做;我认为仅仅创建一个新实例有两大优势:

  • 更快:更改类可以像更新指针一样简单,并更新任何不同的插槽;如果类非常相似,则可以在没有新内存分配的情况下完成此操作
  • 更简单:如果十几个地方已经有了对旧对象的引用,那么创建一个新实例将不会改变他们所指向的内容;如果你需要自己更新每一个,这可能会增加很多复杂性,应该是一个简单的操作(2个单词,在Lisp中)

这并不是说它总是正确的答案,但有能力在你想要的时候做到这一点很好。 “更改实例的类”和“创建一个类似于那个实例的新实例”是非常不同的操作,我希望能够准确地说出我的意思。

答案 4 :(得分:0)

第一个有趣的部分是要知道:为什么你想要/需要一个对象在运行时改变它的类?

有多种选择:

  • 您希望它对应用程序的给定状态的某些方法做出不同的响应。

  • 您可能希望它具有原始类所没有的新功能。

  • 其他......

静态类型语言(如Java和C#)不允许这种情况发生,因为在编译时应该知道对象的类型。

其他编程语言(如Python和Ruby)可能允许这样做(我不确定,但我知道他们可以在运行时添加方法)

对于第一个选项,Charlie Flowers给出的答案是正确的,使用状态模式将允许类表现不同但对象将具有相同的接口。

对于第二个选项,您无论如何都需要更改对象类型,并将其分配给具有额外功能的新引用。因此,您需要创建另一个不同的对象,最终会得到两个不同的对象。