Oop 更改对象类的对象的方法称为什么?

Oop 更改对象类的对象的方法称为什么?,oop,Oop,假设您有一个Person对象,它上面有一个方法,promote(),将其转换为Captain对象。这种类型的方法/交互称为什么 这也感觉像是一种颠倒: myCaptain = new Captain(myPerson); 编辑:感谢所有回复。我遇到这种模式(在Perl中,但在任何地方都相关)的原因纯粹是为了方便。在不知道任何实现交易的情况下,您可以说Captain类“有一个”Person(我知道这可能不是最好的示例,但请确保它不是一个子类) 我假设: // this definition on

假设您有一个
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?
因此,从字面上说,这只是一种方便的方法,用于构建
船长。我只是想知道这种模式是否在野外见过,是否有名字。我猜是的,它并没有真正改变类,而是返回了一个不同的类。但理论上可以,因为我不太在乎原作


Ken++,我喜欢你指出用例的方式。有时候,在内存敏感的环境中适当地更改某些内容真是太棒了。

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

myCaptain = myPerson->ToCaptain();
或者使用构造函数,如您的示例所示:

myCaptain = new Captain(myPerson);
我会称之为转换,甚至是强制转换,这取决于您如何使用对象。如果您有一个值对象:

Person person;
您可以使用构造函数方法隐式强制转换:

Captain captain = person;

(假设C++)

< P>一个简单的解决方法可能是使人的属性为秩。我不知道你的数据结构或需求,但是如果你需要一些试图打破语言基础的东西,那么有可能有更好的方法去做。

你可能想考虑“状态模式”,有时也称为“对象状态”模式。它在《设计模式》一书中有定义,但你很容易在谷歌上找到很多关于它的信息

该模式的一个特点是“对象将显示为更改其类。”

以下是一些链接:


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

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

不过,我从来没有听说过这种特定类型的转换的名称。执行此操作的函数称为
change class

Richard Gabriel在Kiczales之后提出了“变更类协议”,它将元编程CLOS的许多内部内容形式化为“协议”

人们想知道你为什么要这样做;与创建新实例相比,我看到了两大优势:

myCaptain = myPerson->ToCaptain();
  • 更快:更改类可以像更新指针和更新任何不同的插槽一样简单;如果类非常相似,则无需新的内存分配即可完成此操作
  • 更简单:如果十几个地方已经有了对旧对象的引用,那么创建一个新实例不会改变它们指向的对象;如果您需要自己更新每一个,这可能会为一个简单的操作增加很多复杂性(2个单词,用Lisp)

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

第一个有趣的部分是要知道:为什么希望/需要对象在运行时更改其类

有多种选择:

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

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

  • 其他

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

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

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


对于第二个选项,您仍然需要更改对象类型,并将其指定给具有额外功能的新引用。因此,您需要创建另一个不同的对象,并最终得到两个不同的对象。

需要将类更改为OCaptain,以便获得OCaptainmyCaptain@RichB,我不明白你为什么要去奥卡普坦。想解释一下吗?斯特拉格:这是个玩笑。别担心。有人会回滚,Rich可能会让它保持回滚状态。他们说代码不能是诗!;):-/哦,好吧,我想当你花很多时间编辑别人的帖子时就会发生这种情况(myCaptain=Person.ToCaptain()也许?:)+1:我认为简单地允许“Captain”构造函数接受“Person”对象并重新构建它们要干净得多。想象一下,如果你有许多其他职业(“海军上将”等),会发生什么。。。每个类都需要为其他类使用“To*”方法。